需求:图片上传前,将图片裁剪1px,可上传多张图片
步骤:
1.安装插件
npm install vue-cropper
2.创建一个图片裁剪组件,在组件中导入,并注册
<template>
<div class="Cropper">
<div class="cropper-container">
<div class="cropper-el" :style="geth">
<vue-cropper
ref="cropper"
:img="cropperImg"
:output-size="option.size"
:output-type="option.outputType"
:info="true"
:can-move="option.canMove"
:can-move-box="option.canMoveBox"
:fixed-box="option.fixedBox"
:auto-crop="option.autoCrop"
:auto-crop-width="optionWidth"
:auto-crop-height="optionHeigth"
:center-box="option.centerBox"
:high="option.high"
:info-true="option.infoTrue"
@realTime="realTime"
:enlarge="option.enlarge"
:fixed="option.fixed"
:fixed-number="option.fixedNumber"
:limitMinSize="option.limitMinSize"
@imgLoad="imgLoad"
/>
</div>
</div>
</div>
</template>
<script>
import { VueCropper } from "vue-cropper";
export default {
name: "Cropper",
components: {
VueCropper,
},
props: [
"cropperImg",//裁剪图片的URL
"optionWidth",//裁剪框宽
"optionHeigth",//裁剪框高
"geth",//样式
"isDel",//判断是否是裁剪最后一张图
],
data() {
return {
previews: {},
option: {
img: "", // 裁剪图片的地址
size: 1, // 裁剪生成图片的质量
outputType: "png", // 裁剪生成图片的格式 默认jpg
canMove: false, // 上传图片是否可以移动
fixedBox: false, // 固定截图框大小 不允许改变
canMoveBox: false, // 截图框能否拖动
autoCrop: true, // 是否默认生成截图框
// 只有自动截图开启 宽度高度才生效
autoCropWidth: this.optionWidth, // 默认生成截图框宽度
autoCropHeight: this.optionHeigth, // 默认生成截图框高度
centerBox: true, // 截图框是否被限制在图片里面
high: true, // 是否按照设备的dpr 输出等比例图片
enlarge: 1, // 图片根据截图框输出比例倍数
mode: "contain", // 图片默认渲染方式 //图片默认渲染方式 contain , cover, 100px, 100% auto
maxImgSize: 1920, // 限制图片最大宽度和高度
limitMinSize: [10, 10], // 更新裁剪框最小属性
// limitMinSize: 10, // 更新裁剪框最小属性
infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
fixed: false, // 是否开启截图框宽高固定比例 (默认:true)
// fixedNumber: [1, 1] // 截图框的宽高比例 ==>> 这个参数目前没有作用(作者解释的)
fixedNumber: [1, 1], // 截图框的宽高比例
},
};
},
methods: {
// 裁剪时触发的方法,用于实时预览
realTime(data) {
this.previews = data;
// this.$refs.cropper.getCropBlob((data) => {
// console.log("51511515");
// });
this.$refs.cropper.clearCrop();
// console.log(this.previews.url);
// console.log(3333)
},
// 图片加载的回调 imgLoad 返回结果success, error
imgLoad(e) {
if (e === "success") {
this.$nextTick(() => {
// 获取裁剪之后的图片,默认blob,也可以获取base64的图片
this.$refs.cropper.getCropBlob((data) => {
let config = { data: data, isDel: this.isDel };
this.$emit("uploadImg", config);
});
});
}
},
},
};
</script>
<style lang="scss" scoped>
.Cropper {
.cropper-el {
flex-shrink: 0;
}
.cropper-container {
display: block;
justify-content: space-between;
.prive-el {
flex: 1;
align-self: center;
text-align: center;
.prive-style {
margin: 0 auto;
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
overflow: hidden;
background: #ededed;
margin-left: 40px;
}
.preview {
overflow: hidden;
}
.el-button {
margin-top: 20px;
}
}
}
}
</style>
<style lang="scss">
.cropper-box-canvas img {
width: 100% !important;
height: 100% !important;
}
</style>
父组件:
<template>
<div>
<el-form ref="form" :model="form" label-width="7rem" :rules="rules">
<el-form-item label="帖子图片">
<el-upload
class="upload-demo uploadDemoMy"
:action="baseUrl"
multiple
:limit="10"
:file-list="fileListImg"
:auto-upload="false"
accept="image/*"
:show-file-list="true"
:on-remove="handleRemove"
:on-change="handleChangeIMG"
list-type="picture"
>
<el-button size="small" type="primary"
>点击上传</el-button
>
</el-upload>
<div class="ordinaryshowImg">
<div
v-for="(item, index) in cropperImglist"
:key="index"
style="opacity: 0; position: absolute"
>
<vueCropper
:cropperImg="cropperImglist[index]"
:optionWidth="optionWidth"
:optionHeigth="optionHeigth"
:imgH="imgH"
:imgW="imgW"
:geth="geth"
ref="sonCropper"
:isDel="isDel"
@uploadImg="uploadImg"
style="opacity: 0; position: absolute"
/>
</div>
</div>
</el-form-item>
</el-form>
</div>
</template>
<script>
import vueCropper from "./vueCropper.vue";
export default {
components: {
vueCropper,
},
data() {
return {
form: {
postsPicList: [], //图片地址
},
rules: {},
fileListImg: [], //图片List
baseUrl: "",
optionWidth: 0,
optionHeigth: 0,
cropperImglist: [], //url
myimgsrcList: [], //截取后图的url
myimgListdata: [], //截取后图的数据
isDel: 0,
};
},
methods: {
onSubmit() {
this.form.postsPicList = [];
this.$refs.form.validate((valid) => {
if (valid) {
if (this.fileListImg.length != 0) {
this.upLoadfileToServerI();
} else {
this.$message.error("请选择上传的图片或视频");
}
}
});
},
// 裁剪图片
upLoadfileToServerI() {
// 将选中的图片遍历,每张图片都对应一个裁剪框,对裁剪组件隐藏
// this.cropperImglist用来保存选中图片的URL,以此数组循环,得到裁剪组件
this.isDel = 0;
this.fileListImg.forEach((item, index) => {
let file = item.raw;
let url = URL.createObjectURL(file);
this.cropperImglist.push(url);
this.myimgsrcList.push(url);
let that = this;
let img = new Image();
img.src = url;
img.onload = function () {
//改变裁剪框的大小
that.optionWidth = img.width - 1;
that.optionHeigth = img.height - 1;
that.geth = `height:${img.height}px;width:${img.width}px;`;
};
});
},
//移除图片
handleRemove(file, fileList) {
this.fileListImg = fileList;
},
// 选择的图片
handleChangeIMG(file, fileList) {
this.fileListImg = fileList;
},
// 获取截取后的图片,并获取上传链接 裁剪完成后,子组件会触发这个方法,可获取裁剪后的图片
uploadImg(config) {
this.isDel++; //每裁剪一张图 就+1
this.myimgListdata.push(config.data);
// 裁剪到最后一张图片时
if (config.isDel + 1 === this.fileListImg.length) {
console.log(this.myimgListdata); //所有截取后的图片
}
},
},
};
</script>
<style lang="scss" scoped>
</style>
注意:
1.这实际是一个裁剪框组件,需要给一个宽高。
2.由于是自动裁剪,只裁剪1px 裁剪框宽高等于图片宽高-1。
3.经各种尝试,也无法在父组件中直接调用this.$refs.cropper.getCropBlob( )方法,不会执行。
4.不能将裁剪后的图片直接展示出来,会重发触发imgLoad方法,导致图片数量增加。具体需要研究深层的原理。
个人经验,如有更简便的方法欢迎分享