App.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
<template> <div> <!-- Image Upload Button --> <button> <span>Select Image</span> <input ref="uploadInput" type="file" accept="image/jpg, image/jpeg, image/png, image/gif" @change="selectFile" /> </button> <!-- Cropper Modal --> <div v-if="isShowModal" class="modal"> <div class="modal-content"> <VuePictureCropper :boxStyle="{ width: '100%', height: '100%', backgroundColor: '#f8f8f8', margin: 'auto', }" :img="pic" :options="{ viewMode: 1, dragMode: 'crop', aspectRatio: 16 / 9, }" @ready="ready" /> <button @click="getResult">Crop Image</button> <button @click="isShowModal = false">Cancel</button> </div> </div> <!-- Cropped Image Preview --> <div v-if="result.dataURL"> <p>Preview:</p> <img :src="result.dataURL" alt="Cropped Image" /> </div> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; import VuePictureCropper, { cropper } from 'vue-picture-cropper'; export default defineComponent({ components: { VuePictureCropper }, data() { return { isShowModal: false, pic: '', // Stores the uploaded image's base64 string result: { dataURL: '', // Stores cropped image's base64 string }, }; }, methods: { /** * Handles file selection */ selectFile(e: Event) { this.pic = ''; // Clear previous image this.result.dataURL = ''; // Clear previous result const { files } = e.target as HTMLInputElement; if (!files || !files.length) return; const file = files[0]; const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => { this.pic = String(reader.result); // Set uploaded image as cropper input this.isShowModal = true; // Show the cropper modal if (this.$refs.uploadInput) { (this.$refs.uploadInput as HTMLInputElement).value = ''; } }; }, /** * Retrieves cropped image result */ async getResult() { if (!cropper) return; const base64 = cropper.getDataURL(); // Get the cropped image as base64 this.result.dataURL = base64; // Save cropped image preview this.isShowModal = false; // Close the cropper modal }, /** * Logs when the cropper is ready */ ready() { console.log('Cropper is ready.'); }, }, }); </script> <style scoped> .modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); } .modal-content { display: flex; flex-direction: column; align-items: center; } </style> |