vue-cropperjs 基本使用 及其裁剪前压缩,相同图片第二次选择失效,第二次压缩失效,第一次图片转Base64 失效 打印‘data:,' 的问题
cnpm install --save vue-cropperjs
import VueCropper from "vue-cropperjs";
components: { VueCropper },
<div class="crop-demo">
<img :src="cropImg" class="pre-img" />
<div v-show="bendiisshowxiugai[0]" class="crop-demo-btn">
{{$t('lang.Click_change_image')}}
<input
class="crop-input"
type="file"
name="image"
ref="head_picture_file"
accept="image/*"
id="change"
@change="setImage"
/>
</div>
</div>
<el-dialog
:title="$t('lang.Crop_Image')"
:visible.sync="dialogVisible"
width="30%"
>
<vue-cropper
ref="cropper"
:src="imgSrc"
:aspect-ratio="cropperAspectWH"
:ready="cropImage"
:zoom="cropImage"
:cropmove="cropImage"
style="width:100%;height:300px;"
></vue-cropper>
<span slot="footer" class="dialog-footer">
<el-button @click="cancelCrop">{{$t('lang.cancel')}}</el-button>
<el-button type="primary" @click="upladPic">{{$t('lang.confirm')}}</el-button>
</span>
</el-dialog>
//以下五条都是截图插件的 data中的数据
defaultSrc: require("../../../assets/xxx.png"), //默认图片
fileList: [],
imgSrc: "",
cropImg: "",
dialogVisible: false,
img_size: "",
max_fuyuan_defaultSrc: [],
setImage(e) {
let that = this;
let file = e.target.files[0];
if (!file.type.includes("image/")) {
return;
}
this.reader = "";
let canvas = "";
let ctx = "";
let img = "";
that.imgSrc = "";
this.reader = new FileReader();
this.reader.onload = event => {
if (file.size >= 1024 * 1024 * 1) {
console.log("图片过大");
var quality = 1; //压缩图片的质量
canvas = document.createElement("canvas"); //创建画布
ctx = canvas.getContext("2d");
img = new Image();
img.src = event.target.result;
img.onload = function() {
const width = img.width;
const height = img.height;
canvas.width = 800; //这里可以自定义你的图片大小
canvas.height = 800 * (img.height / img.width);
console.log(img.width, img.height, canvas.width, canvas.height); //图片转化时打印'data:,'的原因 就是获取Dom元素img的信息,img onload要比渲染的快,没能拿到宽高。
//所以在下面的that.imgSrc = canvas.toDataURL("image/jpeg", quality);时出现打印'data:,'的情况
setTimeout(() => { //我的解决方案就是用计时器来延迟获取宽高以及转化的操作
ctx.fillRect(0, 0, 0, 0);
ctx.drawImage(img, 0, 0, 800, canvas.height);
that.imgSrc = canvas.toDataURL("image/jpeg", quality); //将图片转为Base64 之后预览要用
that.$refs.cropper &&
that.$refs.cropper[0].replace(that.imgSrc); //第二次压缩失效的原因和解决方法就是这句。。。 that.$refs.cropper[0].replace(that.imgSrc);
that.dialogVisible = true;
}, 50);
};
} else {
that.dialogVisible = true;
that.imgSrc = event.target.result;
that.$refs.cropper &&
that.$refs.cropper[0].replace(event.target.result);
}
};
that.reader.readAsDataURL(file);
},
cropImage() {
this.cropImg = this.$refs.cropper[0].getCroppedCanvas().toDataURL();
},
cancelCrop() {
this.dialogVisible = false;
this.cropImg = this.max_fuyuan_defaultSrc[
this.max_fuyuan_defaultSrc.length - 1
];
$("#change").val(""); //取消change事件 //第二次选择相同图片的时候change事件没有触发所以不会弹出弹窗,要先清除 就是这句。。。
},
upladPic() {
this.sumitImageFile(this.cropImg);
this.dialogVisible = false;
},
sumitImageFile(base64Codes) {
$("#change").val(""); //取消change事件
let that = this;
var formData = new FormData();
//convertBase64UrlToBlob函数是将base64编码转换为Blob
var picName = new Date().getTime() + ".png"; //给截图的文件命名
formData.append(
"file",
that.convertBase64UrlToBlob(base64Codes),
picName
); //append函数的第一个参数是后台获取数据的参数名,和html标签的input的name属性功能相同
this.max_fuyuan_defaultSrc.push(this.imgSrc);
if (this.img_size / 1024 / 1024 < 1.5) {
serviceApi.requestPostUploadFile(formData).then(body => {
that.defaultSrc = body.file_name;
// that.cropImg = that.defaultSrc; //截图用的
});
} else {
this.$message({
message: "要上传图片太大!",
type: "warning"
});
this.max_fuyuan_defaultSrc.pop();
// that.imgSrc=that.cropImg=this.max_fuyuan_defaultSrc;
that.imgSrc = that.cropImg = this.max_fuyuan_defaultSrc[
this.max_fuyuan_defaultSrc.length - 1
];
}
},
//将以base64的图片url数据转换为Blob
convertBase64UrlToBlob(urlData) {
var bytes = window.atob(urlData.split(",")[1]); //去掉url的头,并转换为byte
//处理异常,将ascii码小于0的转换为大于0
var ab = new ArrayBuffer(bytes.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
let size = new Blob([ab], { type: "image/png" });
this.img_size = size.size;
return new Blob([ab], { type: "image/png" });
}
由于时间关系 以上代码并不完全 仅供参考 下次再发叭。。。
另附我找到的相关的好文章
https://segmentfault.com/q/1010000009665100
https://blog.csdn.net/aithena/article/details/103034718
https://www.thinbug.com/q/16077010
https://stackoverflow.com/questions/40908729/html5-canvas-todataurl-returns-data-in-firefox
http://www.360doc.com/content/18/0928/22/13328254_790527851.shtml
https://www.cnblogs.com/goloving/p/8260206.html
http://www.mamicode.com/info-detail-2151760.html
https://www.jianshu.com/p/f9986bd52ec6
https://blog.csdn.net/qq_36538012/article/details/97984553
我遇到的问题 有的有好几种可能的原因 可以参考以上的
首先是用this.cropImg 和this.max_fuyuan_defaultSrc保存 从服务器拿到的最开始的默认图片进行展示和存储,
然后this.max_fuyuan_defaultSrc 用在这数组保存每次在弹窗里截取之后的图片,如果点击取消截取 就返回数组的上一张图片给this.imgSrc在这里显示
弹窗每次点开的时候都进行判断选择的图片是不是大于1M 的 如果是就进行压缩
然后上传给服务器的时候我又判断了一下是不是大于1.5M 中间留了保险的空间哟 如果图片大于1.5M 就又用this.max_fuyuan_defaultSrc进行了回退了