VUE图片裁剪组件,基于VueCropper
搬砖的同志麻烦点个赞支持下
效果图
第一步安装vue-cropper插件
npm install vue-cropper
第二步创建组件,把下面的代码复制过去,注意修改下上传图片的接口
<template>
<a-card :bordered="false">
<div style="font-size: 16px" v-if="hflag">选择图片版式:</div>
<div class="cropper" style="display: flex" >
<div style="width: 25%; display: flex; flex-direction: column; justify-content: center; align-items: center" v-if="hflag">
<div :class="{'col1': hvType, 'col2': !hvType}" class="btn1" @click="chageHVType(1)">
竖版
</div>
<div :class="{'col1': !hvType, 'col2': hvType}" class="btn2" @click="chageHVType(0)">
横板
</div>
</div>
<div style="width: 75%">
<VueCropper
ref="cropper"
:img="option.img"
:outputSize="option.size"
:outputType="option.outputType"
:info="true"
:full="option.full"
:canMove="option.canMove"
:canMoveBox="option.canMoveBox"
:original="option.original"
:autoCrop="option.autoCrop"
:fixed="option.fixed"
:fixedNumber="option.fixedNumber"
:centerBox="option.centerBox"
:infoTrue="option.infoTrue"
:fixedBox="option.fixedBox"
:autoCropWidth="option.autoCropWidth"
:autoCropHeight="option.autoCropHeight"
style="height: 500px; width: 100%"></VueCropper>
</div>
</div>
<div style="display: flex; border-top: 1px solid rgba(0, 0, 0, 0.2); padding-top: 22px; margin-top: 20p; justify-content: flex-end; margin-top: 30px">
<a-button style="width: 120px; height: 48px; font-size: 16px;" @click="close">取消</a-button>
<a-button
style="width: 120px; height: 48px; font-size: 16px;margin-left: 20px;"
key="submit"
type="primary"
:loading="confirmLoading"
@click="finish">确定</a-button>
</div>
</a-card>
</template>
<script>
import {
VueCropper
} from 'vue-cropper'
import {
uploadoss
} from '@/api'
export default {
components: {
VueCropper
},
inject: ['closeCurrent'],
props: {
hflag: {
type: Boolean,
default: () => { return true }
},
fileData: {
type: String,
default: () => { return '' }
},
type: {
type: String,
default: () => { return '' }
},
fixedNumber: {
type: Array,
default: () => { return [9, 16] }
},
autoCropWidth: {
type: Number,
default: () => {
return 300
}
},
autoCropHeight: {
type: Number,
default: () => {
return 300
}
},
fixed: {
type: Boolean,
default: () => {
return true
}
},
centerBox: {
type: Boolean,
default: () => {
return true
}
},
infoTrue: {
type: Boolean,
default: () => {
return true
}
}
},
data() {
return {
confirmLoading: false,
dialogVisible: false,
// 裁剪组件的基础配置option
option: {
img: '', // 裁剪图片的地址
info: true, // 裁剪框的大小信息
outputSize: 1, // 裁剪生成图片的质量
outputType: 'jpeg', // 裁剪生成图片的格式
canScale: false, // 图片是否允许滚轮缩放
autoCrop: true, // 是否默认生成截图框
autoCropWidth: 500, // 默认生成截图框宽度
autoCropHeight: 500, // 默认生成截图框高度
fixedBox: true, // 固定截图框大小 不允许改变
fixed: false, // 是否开启截图框宽高固定比例
fixedNumber: [9, 16], // 截图框的宽高比例
full: true, // 是否输出原图比例的截图
canMoveBox: true, // 截图框能否拖动
original: true, // 上传图片按照原始比例渲染
centerBox: false, // 截图框是否被限制在图片里面
infoTrue: false // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
},
picsList: [], // 页面显示的数组
// 防止重复提交
loading: false,
hvType: 1
}
},
watch: {
infoTrue(e) {
this.option.infoTrue = e
},
centerBox(e) {
this.option.centerBox = e
},
fixed(e) {
this.option.fixed = e
},
autoCropWidth(e) {
this.option.autoCropWidth = e
},
autoCropHeight(e) {
this.option.autoCropHeight = e
},
fileData() {
this.option.img = this.fileData
},
fixedNumber() {
this.option.fixedNumber = this.fixedNumber
}
},
created() {
this.option.fixedNumber = this.fixedNumber
},
methods: {
close() {
this.$emit('close')
},
// 点击裁剪,这一步是可以拿到处理后的地址
finish() {
var that = this
this.confirmLoading = true
this.$refs.cropper.getCropBlob((data) => {
const formData = new FormData()
formData.append('avatar', data)
formData.append('type', this.type)
uploadoss(formData).then(res => {
that.confirmLoading = false
if (res.success != 'false') {
that.$message.success('上传成功')
that.$emit('getUrl', res.path)
that.close()
} else {
that.$message.error('上传失败:' + res.message)
}
})
})
},
chageHVType(e) {
this.hvType = e
if (e == 1) {
this.option.fixedNumber = [9, 16]
} else {
this.option.fixedNumber = [16, 9]
}
this.$refs.cropper.refresh()
}
}
}
</script>
<style scoped>
.btn1 {
width: 63px;
height: 112px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer
}
.btn2 {
width: 112px;
height: 63px;
margin-top: 30px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer
}
.col1 {
border: 2px dashed #70b603;
color: #70b603
}
.col2 {
border: 2px dashed #aaaaaa;
color: #aaa
}
</style>
<style>
.ant-upload.ant-upload-drag .ant-upload {
padding: 16px;
}
</style>
最后一步使用组件
<template>
<Cropper
:fileData="file"
type="pro_main"
v-show="flag"
@close="flag = false"
:autoCropWidth="500"
:autoCropHeight="500"
:hflag="false"
:fixed="false"
:centerBox="false"
:infoTrue="false"
@getUrl="getUrl"></Cropper>
</template>
<script>
export default {
data() {
return {
file:'',
flag:false
}
},
methods: {
addFile(file, fileList) {
console.log(file)
var that = this
// 上传之前判断文件类型
// 图片 1; 视频 2
var type = checkVideoOrImage(file.name)
if (type === 1) {
console.log('type====' + type)
file2Base64(file).then(res => {
// 裁剪
console.log(res)
that.file = res
that.flag = true
})
return false
} else {
this.$message.error('请上传图片格式文件!')
}
}
}
}
function checkVideoOrImage(fileName) {
if (fileName.indexOf('.bmp') > 0 || fileName.indexOf('.png') > 0 || fileName.indexOf('.gif') > 0 || fileName.indexOf(
'.jpg') > 0 || fileName.indexOf('.jpeg') > 0) {
return 1
} else if (fileName.indexOf('.mp4') > 0 || fileName.indexOf('.rmvb') > 0 || fileName.indexOf('.avi') > 0) {
return 2
} else {
return 3
}
}
function file2Base64(file) {
var reader = new FileReader() // 实例化文件读取对象
reader.readAsDataURL(file) // 将文件读取为 DataURL,也就是base64编码
var dataURL = ''
return new Promise((resolve, reject) => {
reader.onload = function(ev) { // 文件读取成功完成时触发
dataURL = ev.target.result // 获得文件读取成功后的DataURL,也就是base64编码
resolve(dataURL)
}
})
}
</script>