前端压缩图片代码,支持移动端和pc 端,还有拍照后获取到的照片
1. upload 使用者调用的方法
2. rotateImg 旋转照片,用于把iOS拍照后获取到的图片摆正
3. dataURLtoFile 将压缩后的图片转为file 对象,区分一个 blob 和 base64, 兼容哪个就用哪个
4. 得先引入 exif-js 用于拿到图片信息,确定 iOS 怎么旋转的
1 /* 2 // 先安装 exif-js 3 4 5 // 监听change事件 6 let file, obj 7 document.querySelector('input[type=file]').addEventListener('change', function (e) { 8 if (e.target.files[0].size / 1024 / 1024 > 20) { 9 alert('上传的照片太大了') 10 return 11 } 12 upload(e, uploadCallback) 13 }) 14 15 // file 新的表单值,可能是个Blob, 16 // obj:{headerImage: '', imgName: ''} headerImage 是base64图片,用于预览上传的图片 17 function uploadCallback (file, obj) { 18 19 let formData = new FormData() 20 formData.append("fileData", file, 'projectname' + new Date().getTime() +'.png') 21 } 22 23 */ 24 import EXIF from 'exif-js' 25 let picValue = null, 26 headerImage = '', 27 imgName = '' 28 const MAXSIZE = 1024 * 1024 / 5 // 大于这个值继续压缩 200k 29 const IMAGEWIDTH = 750 // 重新定义图片宽度,小于这个值就使用原始宽度,防止图片被放大失真 30 31 // 上传 32 function upload(e, cb) { // 入参 1. file change事件中的事件对象, 2. 回调函数 33 let files = e.target.files || e.dataTransfer.files; 34 if (!files.length) return; 35 picValue = files[0]; 36 imgName = picValue.name 37 return imgPreview(picValue, cb); 38 } 39 40 // ios 拍摄的照片可能需要旋转方向使图片方向正常 41 function rotateImg(img, rotateDegree, canvas) { 42 //最小与最大旋转方向,图片旋转4次后回到原方向 43 if (img == null) return; 44 //img的高度和宽度不能在img元素隐藏后获取,否则会出错 45 let height = img.height; 46 let width = img.width; 47 //旋转角度以弧度值为参数 48 let degree = rotateDegree * Math.PI / 180; 49 let ctx = canvas.getContext('2d'); 50 switch (rotateDegree) { 51 case 0: 52 canvas.width = width; 53 canvas.height = height; 54 ctx.drawImage(img, 0, 0); 55 break; 56 case 90: 57 canvas.width = height; 58 canvas.height = width; 59 ctx.rotate(degree); 60 ctx.drawImage(img, 0, -height); 61 break; 62 case 180: 63 canvas.width = width; 64 canvas.height = height; 65 ctx.rotate(degree); 66 ctx.drawImage(img, -width, -height); 67 break; 68 case 270: 69 canvas.width = height; 70 canvas.height = width; 71 ctx.rotate(degree); 72 ctx.drawImage(img, -width, 0); 73 break; 74 } 75 } 76 77 // canvas压缩图片 78 function compress(img, Orientation, cb) { 79 let obj = {} 80 let that = img 81 Orientation = Orientation ? Orientation : '' 82 obj.width = IMAGEWIDTH ? (that.width > IMAGEWIDTH ? IMAGEWIDTH : that.width) : obj.width 83 // 默认按比例压缩 84 let w = that.width, 85 h = that.height, 86 scale = w / h; 87 w = obj.width || w; 88 h = obj.height || (w / scale); 89 let quality = .7; // 默认图片质量为0.7 90 //生成canvas 91 let canvas = document.createElement('canvas'); 92 let ctx = canvas.getContext('2d'); 93 ctx.fillStyle = 'rgba(255, 255, 255, 0)'; 94 // 创建属性节点 95 let anw = document.createAttribute("width"); 96 anw.nodeValue = w; 97 let anh = document.createAttribute("height"); 98 anh.nodeValue = h; 99 canvas.setAttributeNode(anw); 100 canvas.setAttributeNode(anh); 101 ctx.drawImage(that, 0, 0, w, h); 102 // 图像质量 103 if (obj.quality && obj.quality <= 1 && obj.quality > 0) { 104 quality = obj.quality; 105 } 106 if (Orientation && Orientation != 1) { 107 switch (Orientation) { 108 case 6: //需要顺时针(向左)90度旋转 109 rotateImg(that, 90, canvas); 110 break; 111 case 8: //需要逆时针(向右)90度旋转 112 rotateImg(that, 270, canvas); 113 break; 114 case 3: //需要180度旋转 115 rotateImg(that, 180, canvas); //转两次 116 break; 117 } 118 } 119 //进行最小压缩 120 let ndata = canvas.toDataURL('image/jpeg', quality); 121 if (calcBase64ImgSize(ndata) > MAXSIZE) { 122 let img2 = new Image(); 123 img2.src = ndata; 124 img2.onload = function () { 125 compress(img2, '', cb) 126 } 127 } else { 128 headerImage = ndata; 129 try { 130 cb(dataURLtoFile(headerImage, imgName), { 131 headerImage, 132 imgName 133 }) 134 } catch (error) { 135 console.error(error.message); 136 } 137 } 138 } 139 140 // 转为file对象 141 function dataURLtoFile(dataurl, filename) { 142 try { 143 let arr = dataurl.split(','), 144 mime = arr[0].match(/:(.*?);/)[1], 145 bstr = atob(arr[1]), 146 n = bstr.length, 147 u8arr = new Uint8Array(n); 148 while (n--) { 149 u8arr[n] = bstr.charCodeAt(n); 150 } 151 let file = new File([u8arr], filename, { 152 type: mime 153 }); 154 console.log('base64') 155 return file 156 } catch (error) { 157 console.error(error); 158 alert('您的手机不支持上传图片') 159 } 160 } 161 162 // 先看图片大小,小的话直接上传,太大就压缩 163 function imgPreview(file, cb) { 164 // let self = this; 165 let Orientation; 166 //去获取拍照时的信息,解决拍出来的照片旋转问题 167 EXIF.getData(file, function () { 168 Orientation = EXIF.getTag(this, 'Orientation'); 169 // alert(Orientation) 170 }); 171 // 看支持不支持FileReader 172 if (!file || !window.FileReader) return; 173 174 if (/^image/.test(file.type)) { 175 // 创建一个reader 176 let reader = new FileReader(); 177 // 将图片2将转成 base64 格式 178 reader.readAsDataURL(file); 179 // 读取成功后的回调 180 reader.onloadend = function () { 181 let result = this.result; 182 let img = new Image(); 183 img.src = result; 184 //判断图片是否大于50K,是就直接上传,反之压缩图片 185 if (calcBase64ImgSize(result) <= 51200) { 186 headerImage = this.result; 187 cb(dataURLtoFile(headerImage, imgName), { 188 headerImage, 189 imgName 190 }) 191 return 192 } else { 193 img.onload = function () { 194 compress(img, Orientation, cb); 195 } 196 } 197 } 198 } 199 } 200 201 // 计算base64图片大小 202 function calcBase64ImgSize (imgUrl) { 203 var eqTagIndex=imgUrl.indexOf("="); 204 imgUrl=eqTagIndex!=-1?imgUrl.substring(0,eqTagIndex):imgUrl; 205 var strLen=imgUrl.length; 206 return strLen-(strLen/8)*2 207 } 208 export default upload
以上