本文主要讲解基于Vue + Vant,实现移动端图片选择,并用帆布压缩图片,最后上传至服务器。还会封装一个工具类,方便直接调用。
废话不多说先上代码,封装一个CompressImageUtils工具类:
Arunachal Pradesh, *图片压缩工具类 *最大高度和最大宽度都为500,如果超出大小将等比例缩放。 * *注意可能出现压缩后比原图更大的情况,在调用的地方自己判断大小并决定上传压缩前或压缩后的图到服务器。 *///将base64转换为blob 导出功能convertBase64UrlToBlob (urlData) { 让arr=urlData.split (" ") 让mime arr=[0] .match (/: (* & # 63;);/) [1] 让=atob型(arr [1]) 让n=bstr.length 让u8arr=new Uint8Array (n) 而(n)) { u8arr [n]=bstr.charCodeAt (n) } 返回新Blob ([u8arr],{类型:mime}) }//压缩图片 导出功能compressImage(路径){//最大高度 const maxHeight=500;//最大宽度 const maxWidth=500; 返回新的承诺((解决,拒绝)=比;{ 让img=新形象(); img。src=https://www.yisu.com/zixun/path; img。onload=function () { const originHeight=img.height; const originWidth=img.width; 让compressedWidth=img.height; 让compressedHeight=img.width; 如果((originWidth> maxWidth) & & (originHeight> maxHeight)) {//更宽更高, 如果((originHeight/originWidth)> (maxHeight/maxWidth)) {//更加严重的高窄型,确定最大高,压缩宽度 compressedHeight=maxHeight compressedWidth=maxHeight * (originWidth/originHeight) 其他}{//更加严重的矮宽型,确定最大宽,压缩高度 compressedWidth=maxWidth compressedHeight=maxWidth * (originHeight/originWidth) } }else if (originWidth> maxWidth & & originHeight <=maxHeight) {//更宽,但比较矮,以maxWidth作为基准 compressedWidth=maxWidth compressedHeight=maxWidth * (originHeight/originWidth) }else if (originWidth <=maxWidth & & originHeight> maxHeight) {//比较窄,但很高,取maxHight为基准 compressedHeight=maxHeight compressedWidth=maxHeight * (originWidth/originHeight) 其他}{//符合宽高限制,不做压缩 }//生成画布 让帆布=document.createElement(“画布”); 让背景=canvas.getContext (2 d); 画布。身高=compressedHeight; 画布。宽度=compressedWidth; 上下文。clearRect (0, 0, compressedWidth compressedHeight); 上下文。drawImage (img, 0, 0 compressedWidth compressedHeight); 让base64=画布。toDataURL(“图像/*”,0.8); 让blob=convertBase64UrlToBlob (base64);//回调函数返回blob的值。也可根据自己的需求返回base64的值 解决(blob) } }) } >之前
定义的最大宽度和最大高度均为500,如果图片的宽高至少有一个超出了500年,都会被* *等比例* *压缩,不用担心变形。可以根据自己项目需要改变maxWidth和,maxHeight .
这里直接把压缩的最大高度和最大宽度写死为500了,没有在调用时传。因为一个项目压缩的逻辑和大小一般都一致的,没必要在每次调用的时候传。当然如果想写的灵活一点,可以在compressImage方法里再把maxWidth, maxHeight和压缩质量传上。
compressImage方法返回的是blob值,根据服务端接口需要可以改为返回base64,只需将解决(blob)改为解决(base64)即可。
注意一点,对于有些宽高没到500,且分辨率很小的图片,压缩之后可能比之前还大。猜测可能是帆布生成的图片分辨率要比原来高一些,所以最终的图片比压缩前更大。可以在调用的地方加个判断,如果压缩完的大小比原图小,就上传压缩后的图片;如果如果压缩完的大小比原图大,就上传原图。
将CompressImageUtils引入到目标文件,然后调用,compressImage方法,即可在回调里获得压缩后的结果。注意,compressImage方法返回的是诺言。
省略其他无关代码,只保留跟压缩图片和上传相关的:
& lt; template> & lt; div> & lt; van-uploader v模型=拔募斜怼?读完=" afterRead "/比; & lt;/div> & lt;/template> & lt; script> 从“. ./. ./进口{compressImage}跑龙套/CompressImageUtils ' 出口默认{ 组件:{}, 方法:{//读取完图片后 afterRead(文件){ 控制台。日志(“afterRead - - - - - -”,文件); this._compressAndUploadFile(文件); },//压缩图片上传 _compressAndUploadFile(文件){ compressImage (file.content)。(结果=比;{ 控制台。日志(“压缩后的结果”,结果);//结果即为压缩后的结果 控制台。日志(“压缩前大小,file.file.size); 控制台。日志(“压缩后大小,result.size); 如果结果。大小比;file.file.size) { console.log(“上传原图”);//压缩后比原来更大,则将原图上传 this._uploadFile(文件。文件,file.file.name); 其他}{//压缩后比原来小,上传压缩后的 console.log(“上传压缩图”); 这一点。_uploadFile(因此,file.file.name) } }) },//上传图片 _uploadFile(文件,文件名){ 让params=new FormData (); 参数个数。追加(“文件”,文件,文件名); 美元。api.uploadImage (params)。然后(res=比;{ 控制台。日志(uploadImage, res);//上传成功,写自己的逻辑 })。抓住(呃=比;{ 控制台。日志(犯错,犯错); }); }, } } & lt;/script>Vue图片压缩并上传至服务器功能