vue開發:移動端圖片上傳


因為最近遇到個移動端上傳頭像的需求,上傳到后台的數據是base64位,其中為了提高用戶體驗,把比較大的圖片用canvas進行壓縮之后再進行上傳。在移動端調用拍照功能時,會發生圖片旋轉,為了解決這個問題引入了exif去判斷拍照時的信息再去處理圖片,這是個很好的插件。關於exif.js可以去他的GitHub上了解,這邊直接npm install exif-js --save   安裝,然后import一下就可以使用了。以下就是源碼,可以直接使用。

 

[html]  view plain  copy
 
 
 
  1. <template>  
  2.   <div>  
  3.     <div style="padding:20px;">  
  4.       <div class="show">  
  5.         <div class="picture" :style="'backgroundImage:url('+headerImage+')'"></div>  
  6.       </div>  
  7.       <div style="margin-top:20px;">  
  8.         <input type="file" id="upload" accept="image" @change="upload">  
  9.         <label for="upload"></label>  
  10.       </div>  
  11.     </div>  
  12.   </div>  
  13. </template>  
  14.   
  15. <script>  
  16. import Exif from 'exif-js'  
  17.   
  18. export default {  
  19.   data () {  
  20.     return {  
  21.       headerImage:'',picValue:''  
  22.     }  
  23.   },  
  24.   mounted () {  
  25.   },  
  26.   methods: {  
  27.     upload (e) {  
  28.       let files = e.target.files || e.dataTransfer.files;  
  29.       if (!files.length) return;  
  30.       this.picValue = files[0];  
  31.       this.imgPreview(this.picValue);  
  32.     },  
  33.     imgPreview (file) {  
  34.       let self = this;  
  35.       let Orientation;  
  36.       //去獲取拍照時的信息,解決拍出來的照片旋轉問題  
  37.       Exif.getData(file, function(){  
  38.           Orientation = Exif.getTag(this, 'Orientation');  
  39.       });  
  40.       // 看支持不支持FileReader  
  41.       if (!file || !window.FileReader) return;  
  42.   
  43.       if (/^image/.test(file.type)) {  
  44.           // 創建一個reader  
  45.           let reader = new FileReader();  
  46.           // 將圖片2將轉成 base64 格式  
  47.           reader.readAsDataURL(file);  
  48.           // 讀取成功后的回調  
  49.           reader.onloadend = function () {  
  50.             let result = this.result;  
  51.             let img = new Image();  
  52.             img.src = result;  
  53.             //判斷圖片是否大於100K,是就直接上傳,反之壓縮圖片  
  54.             if (this.result.length <= (100 * 1024)) {  
  55.               self.headerImage = this.result;  
  56.               self.postImg();  
  57.             }else {  
  58.               img.onload = function () {  
  59.                 let data = self.compress(img,Orientation);  
  60.                 self.headerImage = data;  
  61.                 self.postImg();  
  62.               }  
  63.             }  
  64.           }   
  65.         }  
  66.       },  
  67.       postImg () {  
  68.         //這里寫接口  
  69.       },  
  70.       rotateImg (img, direction,canvas) {  
  71.         //最小與最大旋轉方向,圖片旋轉4次后回到原方向      
  72.         const min_step = 0;      
  73.         const max_step = 3;        
  74.         if (img == null)return;      
  75.         //img的高度和寬度不能在img元素隱藏后獲取,否則會出錯      
  76.         let height = img.height;      
  77.         let width = img.width;        
  78.         let step = 2;      
  79.         if (step == null) {      
  80.             step = min_step;      
  81.         }      
  82.         if (direction == 'right') {      
  83.             step++;      
  84.             //旋轉到原位置,即超過最大值      
  85.             step > max_step && (step = min_step);      
  86.         } else {      
  87.             step--;      
  88.             step min_step && (step = max_step);      
  89.         }       
  90.         //旋轉角度以弧度值為參數      
  91.         let degree = step * 90 * Math.PI / 180;      
  92.         let ctx = canvas.getContext('2d');      
  93.         switch (step) {      
  94.           case 0:      
  95.               canvas.width = width;      
  96.               canvas.height = height;      
  97.               ctx.drawImage(img, 0, 0);      
  98.               break;      
  99.           case 1:      
  100.               canvas.width = height;      
  101.               canvas.height = width;      
  102.               ctx.rotate(degree);      
  103.               ctx.drawImage(img, 0, -height);      
  104.               break;      
  105.           case 2:      
  106.               canvas.width = width;      
  107.               canvas.height = height;      
  108.               ctx.rotate(degree);      
  109.               ctx.drawImage(img, -width, -height);      
  110.               break;      
  111.           case 3:      
  112.               canvas.width = height;      
  113.               canvas.height = width;      
  114.               ctx.rotate(degree);      
  115.               ctx.drawImage(img, -width, 0);      
  116.               break;  
  117.         }      
  118.     },  
  119.     compress(img,Orientation) {  
  120.       let canvas = document.createElement("canvas");  
  121.       let ctx = canvas.getContext('2d');  
  122.         //瓦片canvas  
  123.       let tCanvas = document.createElement("canvas");  
  124.       let tctx = tCanvas.getContext("2d");  
  125.       let initSize = img.src.length;  
  126.       let width = img.width;  
  127.       let height = img.height;  
  128.       //如果圖片大於四百萬像素,計算壓縮比並將大小壓至400萬以下  
  129.       let ratio;  
  130.       if ((ratio = width * height / 4000000) > 1) {  
  131.         console.log("大於400萬像素")  
  132.         ratio = Math.sqrt(ratio);  
  133.         width /= ratio;  
  134.         height /= ratio;  
  135.       } else {  
  136.         ratio = 1;  
  137.       }  
  138.       canvas.width = width;  
  139.       canvas.height = height;  
  140.   //        鋪底色  
  141.       ctx.fillStyle = "#fff";  
  142.       ctx.fillRect(0, 0, canvas.width, canvas.height);  
  143.       //如果圖片像素大於100萬則使用瓦片繪制  
  144.       let count;  
  145.       if ((count = width * height / 1000000) > 1) {  
  146.         console.log("超過100W像素");  
  147.         count = ~~(Math.sqrt(count) + 1); //計算要分成多少塊瓦片  
  148.   //            計算每塊瓦片的寬和高  
  149.         let nw = ~~(width / count);  
  150.         let nh = ~~(height / count);  
  151.         tCanvas.width = nw;  
  152.         tCanvas.height = nh;  
  153.         for (let i = 0; i count; i++) {  
  154.           for (let j = 0; j count; j++) {  
  155.             tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);  
  156.             ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);  
  157.           }  
  158.         }  
  159.       } else {  
  160.         ctx.drawImage(img, 0, 0, width, height);  
  161.       }  
  162.       //修復ios上傳圖片的時候 被旋轉的問題  
  163.       if(Orientation != "" && Orientation != 1){  
  164.         switch(Orientation){  
  165.           case 6://需要順時針(向左)90度旋轉  
  166.               this.rotateImg(img,'left',canvas);  
  167.               break;  
  168.           case 8://需要逆時針(向右)90度旋轉  
  169.               this.rotateImg(img,'right',canvas);  
  170.               break;  
  171.           case 3://需要180度旋轉  
  172.               this.rotateImg(img,'right',canvas);//轉兩次  
  173.               this.rotateImg(img,'right',canvas);  
  174.               break;  
  175.         }  
  176.       }  
  177.       //進行最小壓縮  
  178.       let ndata = canvas.toDataURL('image/jpeg', 0.1);  
  179.       console.log('壓縮前:' + initSize);  
  180.       console.log('壓縮后:' + ndata.length);  
  181.       console.log('壓縮率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");  
  182.       tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;  
  183.       return ndata;  
  184.     },  
  185.   }  
  186. }  
  187. </script>  
  188.   
  189. <style>  
  190. *{  
  191.   margin: 0;  
  192.   padding: 0;  
  193. }  
  194. .show {  
  195.   width: 100px;  
  196.   height: 100px;  
  197.   overflow: hidden;  
  198.   position: relative;  
  199.   border-radius: 50%;  
  200.   border: 1px solid #d5d5d5;  
  201. }  
  202. .picture {  
  203.   width: 100%;  
  204.   height: 100%;  
  205.   overflow: hidden;  
  206.   background-position: center center;  
  207.   background-repeat: no-repeat;  
  208.   background-size: cover;   
  209. }  
  210. </style>  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM