预期效果:
裁剪时:
裁剪完:
实现方法:
1、安装vue-cropper
npm install vue-cropper
2、写裁剪弹框组件
放在/components/commons/imageCropper/index.vue文件里
这里默认的宽autoCropWidth、高autoCropHeight是400*400,如果想改变裁剪的尺寸,可以在父组件传参
<template>
<div class="image-cropper-modal">
<el-dialog
:visible="visible"
:append-to-body="true"
:close-on-click-modal="false"
title="裁剪图片"
width="700px"
class="image-cropper-dialog"
@close="visible = false"
>
<vue-cropper
ref="imageCropper"
:img="url"
:auto-crop-width="autoCropWidth"
:auto-crop-height="autoCropHeight"
:auto-crop="true"
:fixed="false"
:fixed-number="[1, 1]"
:fixed-box="true"
:output-size="1"
output-type="png"
/>
<template #footer>
<span class="dialog-footer">
<el-button class="common-btn cancel" @click="onCancel">取 消</el-button>
<el-button class="common-btn confirm" type="primary" @click="onConfirm">确 定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script>
import { VueCropper } from 'vue-cropper'
export default {
name: 'ImageCropperModal',
components: {
VueCropper
},
props: {
visible: {
type: Boolean,
default: false
},
url: {
type: String,
default: ''
},
autoCropWidth: {
type: String,
default: `${100 * 4}`
},
autoCropHeight: {
type: String,
default: `${100 * 4}`
}
},
methods: {
onCancel() {
this.$emit('cancel')
},
onConfirm() {
this.$refs.imageCropper.getCropBlob((blob) => {
this.$emit('confirm', blob)
})
}
}
}
</script>
<style lang="scss" scoped>
.image-cropper-dialog {
.vue-cropper {
height: 500px;
}
}
</style>
3、 使用组件
(1)html代码
<el-form
ref="queryForm"
class="formData"
:label-suffix="labelSuffix"
:label-width="labelWidth"
:rules="rulesForm"
:model="queryParams"
style="min-width:900px"
>
<el-form-item label="营业执照上传" prop="companyImgUrl">
<ImageCropperModal
:visible="cropperVisible"
:url="file"
:auto-crop-width="autoCropWidth"
:auto-crop-height="autoCropHeight"
@cancel="cropperVisible = false"
@confirm="onConfirm"
/>
<el-upload
v-model="queryParams.companyImgUrl"
class="avatar-uploader"
action
:auto-upload="false"
:show-file-list="false"
:on-change="changeUpload"
>
<img v-if="queryParams.companyImgUrl" :src="queryParams.companyImgUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon" />
</el-upload>
</el-form-item>
</el-form>
(2)js部分代码
import ImageCropperModal from '@/components/commons/imageCropper/index'
export default {
// ...
components: {
ImageCropperModal
},
data(){
return{
// ...
queryParams: {
companyImgUrl: ''
},
autoCropWidth: '400', // 要裁剪的宽
autoCropHeight: '400', // 要裁剪的高
file: '',
fileName: '', // 存放文件名
cropperVisible: false // 控制弹窗打开关闭
}
},
methods:{
// 文件状态改变时
changeUpload(file) {
var img = file.name.substring(file.name.lastIndexOf('.') + 1)
const suffix = img === 'jpg' || img === 'png' || img === 'jpeg'
if (!suffix) {
this.$message.error('只能上传图片!')
return false
}
// URL.createObjectURL的参数只能是blob或者file类型
// 第一种方法用FileReader,URL.createObjectURL接收blob类型
const reader = new FileReader()
reader.onload = () => {
// 把Array Buffer转化为blob 如果是base64不需要
this.file = typeof reader.result === 'object' ? window.URL.createObjectURL(new Blob([reader.result]))
: reader.result
}
// 转化为base64
this.cropperVisible = true
reader.readAsArrayBuffer(file.raw)
// 第二种方法,URL.createObjectURL接收file类型
// this.$nextTick(() => {
// this.file = URL.createObjectURL(file.raw)
// this.cropperVisible = true
// })
this.fileName = file.name
},
// 点击剪裁弹框的确定按钮
async onConfirm(blob) {
// 这里的new FormData()指,以文件的方式传给后端(FormData的数据)
const form = new FormData()
// new File()的第一个参数是一个字符串数组,数组中的每一个元素对应着文件中一行的内容
// 第二个参数就是文件名字符串
// 第三个参数可以设定一些文件的属性,比如文件的MIME,最后更新时间等
const file = new File([blob], this.fileName, { type: blob.type, lastModified: Date.now() })
file.uid = Date.now()
form.append('file', file)
// 如果想在这里打印查看form的值,会发现它是空对象
// 解决办法,需要用form.get('键')的方法获取值
// console.log(form.get('file'))
// 这里调用接口,获取后端返给的图片地址
const { data } = await upload(form)
this.queryParams.companyImgUrl = data
this.cropperVisible = false
},
}
}
大功告成!
属性:
具体可以参考官网:https://github.com/xyxiao001/vue-cropper