zoukankan      html  css  js  c++  java
  • 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.    100px;  
    196.   height: 100px;  
    197.   overflow: hidden;  
    198.   position: relative;  
    199.   border-radius: 50%;  
    200.   border: 1px solid #d5d5d5;  
    201. }  
    202. .picture {  
    203.    100%;  
    204.   height: 100%;  
    205.   overflow: hidden;  
    206.   background-position: center center;  
    207.   background-repeat: no-repeat;  
    208.   background-size: cover;   
    209. }  
    210. </style>  
  • 相关阅读:
    gdb调试core文件
    设计模式之工厂模式
    设计模式之简单工厂模式
    正确理解python的装饰器
    深入理解MVC架构
    django的模板系统过滤器笔记
    python net-snmp 的使用
    用django写个CMS系统
    django的CMS系统(内容管理系统)
    RESTful 的通俗解释
  • 原文地址:https://www.cnblogs.com/xiaocaiyuxiaoniao/p/9437013.html
Copyright © 2011-2022 走看看