<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>