最近使用vue开发时需要对图片进行裁剪,需求是对图片列表进行修改,点击时弹出裁剪框。
弹框是基于iview进行封装的弹框,跟原生的没多大区别:
<modal :modalForm ="imgModalForm" ref = "imgModal" @onCancel="onCancel">
<div slot="center">
<div class="image-editor">
<Row :gutter="10">
<Col span="14" class="image-editor-con1">
<div class="cropper" ref="cropperbg"><img id="cropimg" alt=""></div>//存放本地图片
</Col>
<Col span="10" class="image-editor-con1">
<Row type="flex" justify="center" align="middle" class="image-editor-con1-preview-con">
<div class="preview" id="preview"></div>//用于存放canvas绘制的裁剪之后的图片
</Row>
<div class="image-editor-con1-btn-con margin-top-10">
<input v-if="setOptions.setBanner==true" type="file" accept="image/png, image/jpeg, image/gif, image/jpg" @change="handleChange($event,'banner')" id="fileinput" class="fileinput" />
<input v-else-if="setOptions.setPage==true" type="file" accept="image/png, image/jpeg, image/gif, image/jpg" @change="handleChange($event,'page')" id="fileinput" class="fileinput" />
<label class="filelabel" for="fileinput"><Icon type="image"></Icon> 选择图片</label>
<span v-if="setOptions.setBanner"><Button @click="handlecrop('banner',imgModalForm.index)" type="primary" icon="crop">裁剪</Button></span>
<span v-else-if="setOptions.setPage"><Button @click="handlecrop('page',0)" type="primary" icon="crop">裁剪</Button></span>
</div>
</Col>
</Row>
</div>
</div>
<div slot="bottom"></div>
</modal>
显示弹框:
//每次点击都清空一遍
cropperImg(index){
this.imgModalForm.index = index; //记录点击的第几个
if (document.querySelector('.cropper-container')) {
document.querySelector('.cropper-container').remove()
}
if(document.querySelector('.preview img')){
document.querySelector('.preview img').remove();
}
if(document.querySelector('.preview')){
document.querySelector('.preview').style='';
}
this.$refs.imgModal.Show();//显示弹框
},
初始化弹框:
具体参数配置请转https://blog.csdn.net/weixin_38023551/article/details/78792400
/**
选择本地图片
*/
handleChange (e,type) {
//项目中多次用到裁剪,通过type来判断 initImg()初始化裁剪框
if(!this.isinit && type=='banner'){
this.initImg(type);
}else if(type=='page' &&!this.ispageinit){
this.initImg(type);
}
let file = e.target.files[0];
let reader = new FileReader();
const that = this;
reader.onload = () => {
that.cropper.replace(reader.result);
reader.onload = null;
};
reader.readAsDataURL(file);
this.filename = file.name;
},
/**
图片裁剪
*/
initImg(type){
let scale;//设置不同裁剪比例
if(type=='banner'){
scale =750/300;
this.isinit=true;
}else if(type=='page'){
scale =750/1206;
this.ispageinit=true;
}
this.cropper = null;//清空绘制图形对象
// 重新渲染画布
let img = document.getElementById('cropimg');
this.cropper = new Cropper(img, {
aspectRatio:scale,
dragMode: 'move',
preview: '#preview',
cropBoxMovable: false,
autoCropArea:1,
cropBoxResizable:false,
});
},
裁剪
handlecrop (type,index) {
if(!this.cropper.url){
alert('请重新选择图片');return;
}
let file = this.cropper.getCroppedCanvas().toDataURL('image/jpeg');
var cropFile = util.dataURLtoFile(file,this.filename);//将base64编码图片转为文件,不要问为什么要转,数据太大界面卡死
if(type=='banner' && cropFile.size > 300 * 1024) {
this.$Notice.warning({
title: '文件大小限制',
desc: '文件大小不超过300KB.'
});
return;
}
if(type=='page' && cropFile.size > 500 * 1024) {
this.$Notice.warning({
title: '文件大小限制',
desc: '文件大小不超过500KB.'
});
return;
}
this.onCancel();//弹框关闭时清除画布
//上传裁剪图片
this.upload(cropFile,type);
},
onCancel(){
if(this.setOptions.setBanner){
this.isinit=false;
}else if(this.setOptions.setPage){
this.ispageinit=false;
}
},
base64图片转为文件:
/**
* 将base64格式图片转为文件
*/
util.dataURLtoFile = function(dataurl, filename) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
上传图片:
upload(file,type){
const that = this;
var formData = new FormData();
formData.append('file', file);
var xhr = new XMLHttpRequest;
xhr.open('post', '/platform/fastdfs/uploadfastdfspic/v1.3');
xhr.send(formData);
xhr.onreadystatechange = function () {
if(xhr.readyState == 4 && xhr.status == 200) {
var data = JSON.parse(xhr.response);
if(type=='page'){
that.resultAllConf.baseConfPO.backgroundImage = data.data;
}else{
that.banner.carouselConfList[that.imgModalForm.index].imgeUrl = data.data;
}
that.$Notice.success({
title: '文件上传成功',
desc: '文件 ' + file.name + ' 上传成功。'
});
that.$refs.imgModal.Close(); //关闭弹框
}
}
}
暂未实现的功能是:想类似于上传QQ头像,点击某个时回携带该图片置于裁剪框中,有想法的请赐教