80 lines
1.8 KiB
Vue
80 lines
1.8 KiB
Vue
![]() |
<template>
|
||
|
<div>
|
||
|
<input type="file" accept="image/*" @change="onFileChange" />
|
||
|
<div v-if="imageSrc" class="cropper-container">
|
||
|
<img ref="image" :src="imageSrc" alt="Image to crop" />
|
||
|
</div>
|
||
|
<button v-if="imageSrc" @click="cropImage">Crop and Upload</button>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script setup>
|
||
|
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||
|
import Cropper from 'cropperjs';
|
||
|
import 'cropperjs/dist/cropper.css';
|
||
|
|
||
|
const imageSrc = ref(null);
|
||
|
const image = ref(null);
|
||
|
let cropper = null;
|
||
|
|
||
|
const onFileChange = (e) => {
|
||
|
const file = e.target.files[0];
|
||
|
if (file) {
|
||
|
const reader = new FileReader();
|
||
|
reader.onload = (event) => {
|
||
|
imageSrc.value = event.target.result;
|
||
|
initCropper();
|
||
|
};
|
||
|
reader.readAsDataURL(file);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const initCropper = () => {
|
||
|
if (cropper) {
|
||
|
cropper.destroy();
|
||
|
}
|
||
|
cropper = new Cropper(image.value, {
|
||
|
aspectRatio: 1, // Set aspect ratio (e.g., 1 for square)
|
||
|
viewMode: 1, // Restrict the crop box to the size of the image
|
||
|
});
|
||
|
};
|
||
|
|
||
|
const cropImage = () => {
|
||
|
if (cropper) {
|
||
|
const croppedCanvas = cropper.getCroppedCanvas();
|
||
|
croppedCanvas.toBlob((blob) => {
|
||
|
uploadImage(blob);
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const uploadImage = async (blob) => {
|
||
|
const formData = new FormData();
|
||
|
formData.append('image', blob, 'cropped-image.png');
|
||
|
|
||
|
try {
|
||
|
const response = await $fetch('/api/upload', {
|
||
|
method: 'POST',
|
||
|
body: formData,
|
||
|
});
|
||
|
alert('Image uploaded successfully!');
|
||
|
console.log('Upload response:', response);
|
||
|
} catch (error) {
|
||
|
console.error('Error uploading image:', error);
|
||
|
alert('Error uploading image');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
onBeforeUnmount(() => {
|
||
|
if (cropper) {
|
||
|
cropper.destroy();
|
||
|
}
|
||
|
});
|
||
|
</script>
|
||
|
|
||
|
<style scoped>
|
||
|
.cropper-container {
|
||
|
max-width: 100%;
|
||
|
margin-top: 20px;
|
||
|
}
|
||
|
</style>
|