项目重要实现对图片的裁剪,先看最终实现效果吧。
网上搜了很多组件,之前Vue2中使用的是vue-img-cutter组件,非常方便,但是不知道为啥在Vue3中就一直报错,那就只能换成VueCropper,说一下两者的区别,后者的封装程度远远没有前者,前者把上传、旋转、缩放等功能都已经封装好了,后者则需要自己写代码时间,话不多说,开始撸码。
主体是vuecrpooer组件,下方代码实现自定义事件。
<div style="width:450px;height:400px">
<vueCropper ref="cropperRef" :img="option.img" :outputSize="option.size" :outputType="option.outputType"
:info="true" :full="option.full" :canMove="option.canMove" :canMoveBox="option.canMoveBox"
:original="option.original" :canScale="option.canScale" :autoCrop="option.autoCrop"
:fixed="option.fixed" :fixedNumber="option.fixedNumber" :centerBox="option.centerBox"
:infoTrue="option.infoTrue" :fixedBox="option.fixedBox" :autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight" :maxImgSize="option.maxImgSize"></vueCropper>
<br />
<!-- 以下是实现自定义button事件,包括选择图片,旋转,提交等 -->
<el-upload action="#" :before-upload="beforeUpload" accept="image/png, image/jpeg, image/jpg">
<el-button type="success" size="small">选择图片</el-button>
<template #tip>
<div class="el-upload__tip">
仅支持jpg/png图片,不得超过2M
</div>
</template>
<!-- 一定要加上stop修饰符,否则以下任何一个button都会出发上传功能 -->
<el-button type="success" @click.stop="handleLeft" size="mini"><i
class="iconfont icon-zuozhuan- el-icon--center"></i>
</el-button>
<el-button type="success" @click.stop="handleRight" size="mini"><i
class="iconfont icon-youzhuan- el-icon--center"></i>
</el-button>
<el-button size="small" @click.stop="isShow=false">取消</el-button>
<el-button size="small" type="primary" @click.stop="handleDialogOK">提交</el-button>
</el-upload>
</div>
VueCropper属性对应值如下,实际并不需要全部罗列出来,很多属性都有默认值的,我这里只是为了方便记忆,具体可以见官网,都是中文的哦。
option: {
img: '', // 裁剪图片的地址
info: true, // 裁剪框的大小信息
outputSize: 0.8, // 裁剪生成图片的质量
outputType: 'jpeg', // 裁剪生成图片的格式
canScale: true, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 400, // 默认生成截图框宽度
autoCropHeight: 185, // 默认生成截图框高度
fixedBox: true, // 固定截图框大小 不允许改变
fixed: true, // 是否开启截图框宽高固定比例
fixedNumber: [300, 185], // 截图框的宽高比例
full: false, // 是否输出原图比例的截图
canMoveBox: true, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: true, // 截图框是否被限制在图片里面
infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
maxImgSize: 800 //限制图片最大宽度和高度
}
el-upload组件中before-upload方法,主要是图片尺寸格式进行一下验证,然后实现本地图片的加载,当选择本地图片的时候,通过getBase64方法转换一下图片,此方法网上一大串我这里就不粘贴了,然后就可以将图片加载到VueCropper组件中。
const beforeUpload = (file) => {
if (file.type != 'image/jpeg' && file.type != 'image/png') {
ElMessage({
type: 'error',
message: '必须是jpg或者png图片',
})
return false
} else if (file.size / 1024 / 1024 > 2) {
ElMessage({
type: 'error',
message: '图片不能大于2M',
})
return false
} else {
// 将图片转换成base64格式
// vuecropper支持url、base64、blob三种格式
getBase64(file).then(res => {
state.option.img = res
})
return false
}
}
向左、向右旋转代码就非常简单了。
const handleLeft = () => {
cropperRef.value.rotateLeft()
}
const handleRight = () => {
cropperRef.value.rotateRight()
}
最后就是提交了,通过cropperRef.value.getCropBlob方法获得最终裁剪后的图片,即可。
const handleDialogOK = () => {
cropperRef.value.getCropBlob((data) => {
let fileExt = '' // 文件扩展名
if (data.type === 'image/jpeg') {
fileExt = 'jpg'
} else if (data.type === 'image/png') {
fileExt = 'png'
} else {
ElMessage({
type: 'error',
message: '必须是jpg或者png图片',
})
return false
}
const date = new Date()
const filePath =
`articlecover/${date.getFullYear()}/${date.getMonth() + 1}/${random(12)}.${fileExt}`
//上传阿里云服务器
client.put(filePath, data)
.then((res) => {
// 上传业务逻辑
})
}
此项目有一个缺点,没有实现实时预览,不过项目中此功能并非必须,我也尝试过实现,不过代码非常复杂,等有时间再研究吧。更多详细内容可以访问VueCropper官网。