前端压缩图片代码,支持移动端和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

 

 

以上

 

posted @ 2019-04-17 17:39  blackbentel  阅读(579)  评论(0编辑  收藏  举报