实现功能:
在上传图片之前,按照一定比例或不规则进行剪裁,剪裁后上传到服务器,实现绝大部分的图片裁剪上传的需求,代码有注释。
效果图:
安装
npm install vue-cropper
使用
import { VueCropper } from 'vue-cropper'
上传图片
html
<el-upload
action=""
:class="['image-uploader']"
:show-file-list="false"
:accept="accept"
:auto-upload="false"
:on-change="changeUpload"
>
<slot>
<div v-if="value" class="image-slot">
<img v-if="/(.+)\.(gif|png|jpg|jpeg)$/.test(value)" :src="value" :style="{maxWidth:size,maxHeight:size}">
<span @click.stop="$emit('input', '')">点击移除</span>
</div>
<el-button v-else type="primary" icon="el-icon-plus">选择图片</el-button>
</slot>
</el-upload>
<el-dialog title="图片剪裁" center width="500px" :visible.sync="clipVisible" append-to-body>
<div class="cropper-content">
<div class="cropper" style="text-align:center">
<vueCropper
ref="cropper"
:img="clipOption.img"
:output-size="clipOption.outputSize"
:output-type="clipOption.outputType"
:info="clipOption.info"
:can-scale="clipOption.canScale"
:auto-crop="clipOption.autoCrop"
:auto-crop-width="clipOption.autoCropWidth"
:auto-crop-height="clipOption.autoCropHeight"
:fixed="clipOption.fixed"
:fixed-box="clipOption.fixedBox"
:fixed-number="clipOption.fixedNumber"
/>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="clipVisible = false">取 消</el-button>
<el-button type="primary" :loading="loading" @click="finish">确认</el-button>
</div>
</el-dialog>
<script>
import { uploadFile } from '@/api/user'
import { VueCropper } from 'vue-cropper'
export default {
name: 'UploadClipImage',
components: {
VueCropper
},
props: {
value: {
type: [Array, String],
default() {
return ''
}
},
required: {
type: Boolean,
default: false
},
oss: {
type: [String, Number],
default: 0
},
dirName: { // 上传路径
type: [String, Number],
default: 'admin-uploads/'
},
accept: {
type: String,
default: 'image/gif,image/png,image/jpg,image/jpeg'
},
size: { // 图片大小
type: String,
default: 'auto'
},
pictureSize: { // 上传图片大小
type: Number,
default: 0.3
},
fixedNumber: { // 裁剪比例
type: Array,
default() {
return [1, 1]
}
},
outputSize: { // 裁剪后图片质量
type: Number,
default: 0.8
},
outputType: { // 裁剪后图片格式
type: String,
default: 'jpg'
},
fixed: { // 是否开启截图框宽高固定比例, 若为false,fixedNumber比例无效
type: Boolean,
default: true
}
},
data() {
return {
file_list: [],
clipVisible: false,
clipOption: {
img: '', // 裁剪图片的地址
info: true, // 裁剪框的大小信息
outputSize: this.outputSize, // 裁剪生成图片的质量
outputType: this.outputType, // 裁剪生成图片的格式
canScale: false, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 280, // 默认生成截图框宽度
autoCropHeight: 280, // 默认生成截图框高度
fixedBox: false, // 截图框大小固定 不允许改变
fixed: this.fixed,
fixedNumber: this.fixedNumber,
full: true, // 是否输出原图比例的截图
canMoveBox: false, // 截图框能否拖动
original: false, // 上传图片按照原始比例渲染
centerBox: false, // 截图框是否被限制在图片里面
infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
canMove: true
},
loading: false,
fileinfo: {}
}
},
computed: {
labelString() {
if (typeof this.$attrs.label === 'string') {
return this.$attrs.label
}
return '上传图片:'
}
},
methods: {
remove(name) {
const index = this.file_list.findIndex(v => v.url === name)
if (index >= 0) {
this.file_list.splice(index, 1)
this.$emit('input', this.file_list)
}
},
finish() { // 确定裁剪
this.loading = true
this.$refs.cropper.getCropBlob((data) => {
const params = new FormData()
params.append('file', data, this.fileinfo.name)
params.append('dir_name', this.dirName)
params.append('to_OSS', this.oss)
uploadFile(params).then(res => {
if (res.data) {
this.$emit('input', res.data)
this.loading = false
this.clipVisible = false
}
})
})
},
changeUpload(file, fileList) {
const isImage = /image\/[gif|png|jpg|jpeg]/i.test(file.raw.type)
let imageSize = file.raw.size / 1024 / 1024 < 0.3
if (this.pictureSize && isImage) {
imageSize = file.size / 1024 / 1024 < this.pictureSize
}
if (isImage) {
if (isImage && !imageSize) {
this.$message.error(`上传图片大小不能超过 ${this.pictureSize}M !`)
return false
} else {
this.fileinfo = file
const url = URL.createObjectURL(file.raw) // 创建一个临时路径
this.$nextTick(() => {
this.clipOption.img = url
this.clipVisible = true
})
}
} else {
this.$message.error('仅支持上传 png/jpg/jpeg/gif 格式图片')
return false
}
}
}
}
</script>
结束语:创作不易,动动小手点个赞再走呗~👍,具体不清楚可以联系我哦✌️