feat: 시그니처 이미지 등록 시 1:1 크롭 기능을 추가한다

This commit is contained in:
Yu Sung
2026-02-27 20:00:57 +09:00
parent 5960d01ee9
commit b976b93464
2 changed files with 149 additions and 2 deletions

View File

@@ -369,11 +369,50 @@
</v-card>
</v-dialog>
</v-row>
<v-dialog
v-model="show_cropper_dialog"
max-width="800px"
persistent
>
<v-card>
<v-card-title>이미지 크롭 (1:1 비율)</v-card-title>
<v-card-text>
<div class="cropper-wrapper">
<img
ref="cropper_image"
:src="cropper_image_url"
alt="Cropper Image"
class="cropper-image"
>
</div>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
color="grey darken-1"
text
@click="cancelCropper"
>
취소
</v-btn>
<v-btn
color="blue darken-1"
text
@click="cropImage"
>
크롭 완료
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
import * as api from "@/api/signature";
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';
export default {
name: "SignatureManagement",
@@ -399,6 +438,10 @@ export default {
selected_signature_can: {},
sort_type: 'NEWEST',
show_cropper_dialog: false,
cropper_image_url: '',
cropper: null,
headers: [
{
text: '캔',
@@ -450,13 +493,70 @@ export default {
imageAdd(payload) {
const file = payload;
if (file) {
this.image_url = URL.createObjectURL(file)
URL.revokeObjectURL(file)
if (file._isCropped) return;
if (file.type === 'image/gif') {
this.image = file
this.image_url = URL.createObjectURL(file)
return
}
this.cropper_image_url = URL.createObjectURL(file)
this.show_cropper_dialog = true
this.$nextTick(() => {
if (this.cropper) {
this.cropper.destroy()
}
this.cropper = new Cropper(this.$refs.cropper_image, {
aspectRatio: 1,
viewMode: 1,
})
})
} else {
this.image_url = null
this.image = null
}
},
cancelCropper() {
this.show_cropper_dialog = false
if (this.cropper) {
this.cropper.destroy()
this.cropper = null
}
this.cropper_image_url = ''
this.image = null
this.image_url = null
},
cropImage() {
const canvas = this.cropper.getCroppedCanvas()
let finalCanvas = canvas
const MAX_WIDTH = 800
if (canvas.width > MAX_WIDTH) {
const height = MAX_WIDTH
const resizeCanvas = document.createElement('canvas')
resizeCanvas.width = MAX_WIDTH
resizeCanvas.height = height
const ctx = resizeCanvas.getContext('2d')
ctx.drawImage(canvas, 0, 0, MAX_WIDTH, height)
finalCanvas = resizeCanvas
}
finalCanvas.toBlob((blob) => {
const file = new File([blob], 'signature_image.png', {type: 'image/png'})
file._isCropped = true
this.image = file
this.image_url = URL.createObjectURL(blob)
this.show_cropper_dialog = false
if (this.cropper) {
this.cropper.destroy()
this.cropper = null
}
}, 'image/png')
},
showWriteDialog() {
this.show_write_dialog = true
},
@@ -713,4 +813,14 @@ export default {
font-weight: bold;
color: #3bb9f1;
}
.cropper-wrapper {
max-height: 500px;
width: 100%;
}
.cropper-image {
display: block;
max-width: 100%;
}
</style>