文件地址:https://github.com/xyxiao001/vue-cropper
安裝:
npm install vue-cropper
子元件
<template> <el-dialog title="裁剪頭像" :visible.sync="dialogVisible" :show-close="false" :close-on-click-modal="false" :close-on-press-escape="false" width="600px" append-to-body @close="closeDialog" > <div class="avatar-container"> <!-- 待上傳圖片 --> <div v-show="!options.img"> <el-upload ref="upload" class="upload" action="" :on-change="upload" accept="image/png, image/jpeg, image/jpg" :show-file-list="false" :auto-upload="false" > <el-button slot="trigger" ref="uploadBtn" size="small" type="primary"> 選擇圖片 </el-button> </el-upload> <div>支援jpg、png格式的圖片,大小不超過5M</div> </div> <!-- 已上傳圖片 --> <div v-show="options.img" class="avatar-crop"> <vueCropper v-if="dialogVisible" ref="cropper" class="crop-box" :img="options.img" :auto-crop="options.autoCrop" :fixed-box="options.fixedBox" :can-move-box="options.canMoveBox" :auto-crop-width="options.autoCropWidth" :auto-crop-height="options.autoCropHeight" :center-box="options.centerBox" :fixed="options.fixed" :fixed-number="options.fixedNumber" :can-move="options.canMove" :can-scale="options.canScale" /> </div> </div> <span slot="footer" class="dialog-footer"> <div class="reupload" @click="reupload"> <span v-show="options.img">重新上傳</span> </div> <div> <el-button @click="closeDialog">取 消</el-button> <el-button type="primary" @click="getCrop">確 定</el-button> </div> </span> <!-- </el-dialog> --> </el-dialog> </template> <script> import { VueCropper } from 'vue-cropper' export default { name: 'AvatarCropper', components: { VueCropper }, props: { dialogVisible: { type: Boolean, default: false } }, data() { return { // vueCropper元件 裁剪配置資訊 options: { name: '', img: '', // 原圖檔案 autoCrop: true, // 預設生成截圖框 fixedBox: false, // 固定截圖框大小 canMoveBox: true, // 截圖框可以拖動 autoCropWidth: 200, // 截圖框寬度 autoCropHeight: 200, // 截圖框高度 fixed: false, // 截圖框寬高固定比例 fixedNumber: [1, 1], // 截圖框的寬高比例 centerBox: true, // 截圖框被限制在圖片裡面 canMove: false, // 上傳圖片不允許拖動 canScale: true // 上傳圖片不允許滾輪縮放 } } }, methods: { // 讀取原圖 upload(file) { const isIMAGE = file.raw.type === 'image/jpeg' || file.raw.type === 'image/png' const isLt5M = file.raw.size / 1024 / 1024 < 5 if (!isIMAGE) { this.$message({ showClose: true, message: '請選擇 jpg、png 格式的圖片', type: 'warning' }) return false } if (!isLt5M) { this.$message({ showClose: true, message: '圖片大小不能超過 5MB', type: 'warning' }) return false } const reader = new FileReader() reader.readAsDataURL(file.raw) reader.onload = e => { this.options.name = file.name this.options.img = e.target.result // base64 } }, // 獲取截圖資訊 getCrop() { // 獲取截圖的 blob 資料 this.$refs.cropper.getCropBlob((data) => { this.$emit('closeAvatarDialog', data, this.options.name) this.closeDialog() }) }, // 重新上傳 reupload() { this.$refs.uploadBtn.$el.click() }, // 關閉彈框 closeDialog() { this.$emit('update:dialogVisible', false) this.options.img = '' } } } </script> <style lang="scss" scoped> .dialog-footer { display: flex; justify-content: space-between; align-items: center; font-size: 14px; .reupload { color: #409eff; cursor: pointer; } } .avatar-container { display: flex; justify-content: center; align-items: center; width: 560px; height: 400px; background-color: #f0f2f5; margin-right: 10px; border-radius: 4px; .upload { text-align: center; margin-bottom: 24px; } .avatar-crop { width: 560px; height: 400px; position: relative; .crop-box { width: 100%; height: 100%; border-radius: 4px; overflow: hidden; } } } </style>
父元件
<template> <div> <el-button @click="dialogVisible = true">上傳頭像</el-button> <avatar-cropper :dialogVisible.sync="dialogVisible" @closeAvatarDialog="closeAvatarDialog"></avatar-cropper> </div> </template> <script> import avatarCropper from '@/components/avatarCropper' export default { components: { avatarCropper }, data() { return { dialogVisible: false } }, methods: { closeAvatarDialog(data) { console.log(data) this.dialogVisible = false } } } </script>