前端壓縮圖片代碼,支持移動端和pc 端,還有拍照後獲取到的照片

1. upload   使用者調用的方法node

2. rotateImg  旋轉照片,用於把iOS拍照後獲取到的圖片擺正canvas

3. dataURLtoFile 將壓縮後的圖片轉爲file 對象,區分一個 blob 和 base64, 兼容哪一個就用哪一個函數

4. 得先引入  exif-js  用於拿到圖片信息,肯定 iOS 怎麼旋轉的this

 

  1 import EXIF from 'exif-js'
  2 var picValue = null,
  3   headerImage = '',
  4   imgName = '',
  5   imgType = ''
  6 const MAXSIZE = 1024
  7 
  8 function upload(e, cb) { // 入參 1. file change事件中的事件對象, 2. 回調函數
  9   var files = e.target.files || e.dataTransfer.files;
 10   if (!files.length) return;
 11   picValue = files[0];
 12   imgName = picValue.name
 13   imgType = picValue.type.split('/')[1]
 14   return imgPreview(picValue, cb);
 15 }
 16 
 17 function rotateImg(img, rotateDegree, canvas) {
 18   //最小與最大旋轉方向,圖片旋轉4次後回到原方向    
 19   if (img == null) return;
 20   //img的高度和寬度不能在img元素隱藏後獲取,不然會出錯    
 21   let height = img.height;
 22   let width = img.width;
 23   //旋轉角度以弧度值爲參數    
 24   let degree = rotateDegree * Math.PI / 180;
 25   let ctx = canvas.getContext('2d');
 26   switch (rotateDegree) {
 27     case 0:
 28       canvas.width = width;
 29       canvas.height = height;
 30       ctx.drawImage(img, 0, 0);
 31       break;
 32     case 90:
 33       canvas.width = height;
 34       canvas.height = width;
 35       ctx.rotate(degree);
 36       ctx.drawImage(img, 0, -height);
 37       break;
 38     case 180:
 39       canvas.width = width;
 40       canvas.height = height;
 41       ctx.rotate(degree);
 42       ctx.drawImage(img, -width, -height);
 43       break;
 44     case 270:
 45       canvas.width = height;
 46       canvas.height = width;
 47       ctx.rotate(degree);
 48       ctx.drawImage(img, -width, 0);
 49       break;
 50   }
 51 }
 52 
 53 function compress(img, Orientation, cb) {
 54   let obj = {}
 55   let that = img
 56   Orientation = Orientation ? Orientation : ''
 57   // obj.width = that.width > 750 ? 750 : that.width
 58   // 默認按比例壓縮
 59   let w = that.width,
 60     h = that.height,
 61     scale = w / h;
 62   w = obj.width || w;
 63   h = obj.height || (w / scale);
 64   let quality = .7; // 默認圖片質量爲0.7
 65   //生成canvas
 66   let canvas = document.createElement('canvas');
 67   let ctx = canvas.getContext('2d');
 68   ctx.fillStyle = 'rgba(255, 255, 255, 0)';
 69   // 建立屬性節點
 70   let anw = document.createAttribute("width");
 71   anw.nodeValue = w;
 72   let anh = document.createAttribute("height");
 73   anh.nodeValue = h;
 74   canvas.setAttributeNode(anw);
 75   canvas.setAttributeNode(anh);
 76   ctx.drawImage(that, 0, 0, w, h);
 77   // 圖像質量
 78   if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
 79     quality = obj.quality;
 80   }
 81   if (Orientation && Orientation != 1) {
 82     switch (Orientation) {
 83       case 6: //須要順時針(向左)90度旋轉
 84         rotateImg(that, 90, canvas);
 85         break;
 86       case 8: //須要逆時針(向右)90度旋轉
 87         rotateImg(that, 270, canvas);
 88         break;
 89       case 3: //須要180度旋轉
 90         rotateImg(that, 180, canvas); //轉兩次
 91         break;
 92     }
 93   }
 94   //進行最小壓縮
 95   let ndata = canvas.toDataURL('image/jpeg', quality);
 96 
 97   if (ndata.length > MAXSIZE) {
 98     console.log(ndata.length);
 99     let img2 = new Image();
100     img2.src = ndata;
101     img2.onload = function () {
102       compress(img2, '', cb)
103     }
104   } else {
105     headerImage = ndata;
106     try {
107       cb(dataURLtoFile(headerImage, imgName), {
108         headerImage,
109         imgName
110       })
111     } catch (error) {
112       console.error(error.message);
113     }
114   }
115 }
116 
117 function dataURLtoFile(dataurl, filename) { //轉換爲file對象
118   try {
119     let arr = dataurl.split(','),
120       mime = arr[0].match(/:(.*?);/)[1],
121       bstr = atob(arr[1]),
122       n = bstr.length,
123       u8arr = new Uint8Array(n);
124     while (n--) {
125       u8arr[n] = bstr.charCodeAt(n);
126     }
127     let blob = new Blob([u8arr], {
128       type: mime
129     });
130     return blob
131   } catch (error) {
132     try {
133       let arr = dataurl.split(','),
134         mime = arr[0].match(/:(.*?);/)[1],
135         bstr = atob(arr[1]),
136         n = bstr.length,
137         u8arr = new Uint8Array(n);
138       while (n--) {
139         u8arr[n] = bstr.charCodeAt(n);
140       }
141       let file = new File([u8arr], filename, {
142         type: mime
143       });
144       return file
145     } catch (error) {
146       console.error(error);
147       alert('您的手機不支持上傳圖片')
148     }
149   }
150 }
151 
152 function imgPreview(file, cb) {
153   // let self = this;
154   let Orientation;
155   //去獲取拍照時的信息,解決拍出來的照片旋轉問題
156   EXIF.getData(file, function () {
157     Orientation = EXIF.getTag(this, 'Orientation');
158     // alert(Orientation)
159   });
160   // 看支持不支持FileReader
161   if (!file || !window.FileReader) return;
162 
163   if (/^image/.test(file.type)) {
164     // 建立一個reader
165     let reader = new FileReader();
166     // 將圖片2將轉成 base64 格式
167     reader.readAsDataURL(file);
168     // 讀取成功後的回調
169     reader.onloadend = function () {
170       let result = this.result;
171       let img = new Image();
172       img.src = result;
173       //判斷圖片是否大於100K,是就直接上傳,反之壓縮圖片
174       if (this.result.length <= MAXSIZE) {
175         headerImage = this.result;
176         cb(dataURLtoFile(headerImage, imgName), {
177           headerImage,
178           imgName
179         })
180         return
181       } else {
182         img.onload = function () {
183           compress(img, Orientation, cb);
184         }
185       }
186     }
187   }
188 }
189 export default upload

 

 

以上url

相關文章
相關標籤/搜索