zoukankan      html  css  js  c++  java
  • 移动端原生JS上传图片(含图片压缩和方向处理、ajax上传)

    基本思路

    • 监听 input file 的 change 事件,获取到上传的文件信息
    • 使用 FileReader 对象读取文件的 base64 格式,赋值给 img 显示
    • 将图片绘制在 canvas 上,控制图片绘制的宽度,超过宽度,等比缩放。
    • 利用 exif.js 获取图片的方向信息,解决 ios 上竖直照片翻转

    基础代码

    你只需要一个简简单单的 input 即可,当然,要显示预览图片,肯定还需要一个 img 标签。此外,原生的 input 标签比较丑,为了美观起见,一般都会把 input 透明度设置成 0,然后自定义个按钮的样式盖在上面,样式这里就不详细讲了,easy。

    <input type="file" name="image" accept=“image/*” onchange='handleInputChange' id="upload-img">
    <img src="" class="prev-img">
    

    兼容性

    • 安卓上不支持 multiple 属性,即不能一次多选
    • 因为调用的是系统原生的文件读取,每个机型显示的页面不一样,难以测试

    完整的封装 Class 如下,如果不需要压缩或者方向处理,直接注释即可。

    export default class Uploader {
      constructor() {
    
      }
    
      /**
       * 把base64格式转化成Blob格式
       * @param  {[type]} urlData [description]
       * @return {[type]}         [description]
       */
      convertBase64UrlToBlob(urlData) {
        var arr = urlData.split(','),
          mime = arr[0].match(/:(.*?);/)[1],
          bstr = atob(arr[1]),
          n = bstr.length,
          u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], {
          type: mime
        });
      }
    
      /**
       * 外部调用的方法 完成图片的压缩
       * @param  {[type]}   file     需要处理的file对象
       * @param  {[type]}   obj      传入的配置 quality 压缩的质量
       * @param  {Function} callback 完成压缩之后的回调函数
       * @return {[type]}            [description]
       */
      photoCompress(file, obj, callback) {
        // 使用HTML5的FileReader开始读取File对象中的内容
        let setting = obj;
        var ready = new FileReader();
        ready.readAsDataURL(file);
        var that = this;
        // 判断图片需不需要压缩
        if (file.size / 1024 < 500) {
          setting.quality = .9;
        } else {
          setting.quality = .5;
        }
        
        // 获取图片源信息 判断照片方向
        ready.onload = function () {
          var _this2 = this;
          that.getOrientation(file).then(function(o){
          // setting.orientation = EXIF.getTag(file, "Orientation");
          setting.orientation = o;
          var re = _this2.result;
          that.canvasDataURL(re, setting, callback, file)
          })
        }
        
    
    
      }
    
      /**
       * canvas绘制
       * @param  {[type]}   result     [description]
       * @param  {[type]}   obj      [description]
       * @param  {Function} callback [description]
       * @return {[type]}            [description]
       */
      canvasDataURL(result, obj, callback, file) {
        var img = new Image();
        img.src = result;
        var _this = this;
        img.onload = function() {
          var that = this;
          var w, h, scale, quality;
          scale = that.width / that.height;
          if (that.width > 1200) {
            w = 1200;
            h = w / scale;
          } else {
            w = that.width;
            h = that.height;
          }
          //生成canvas
          var canvas = document.createElement('canvas');
          var ctx = canvas.getContext('2d');
          // 创建属性节点
          var anw = document.createAttribute("width");
          anw.nodeValue = w;
          var anh = document.createAttribute("height");
          anh.nodeValue = h;
          canvas.setAttributeNode(anw);
          canvas.setAttributeNode(anh);
          // 调整图片方向
          // console.log(obj.orientation)
          if (obj.orientation && obj.orientation != "" && obj.orientation != 1) {
            switch (obj.orientation) {
              case 6: //需要顺时针(向左)90度旋转
                _this.rotateImg(that, w, h, 'left', canvas, ctx);
                break;
              case 8: //需要逆时针(向右)90度旋转
                _this.rotateImg(that, w, h, 'right', canvas, ctx);
                break;
              case 3: //需要180度旋转
                _this.rotateImg(that, w, h, 'right', canvas, ctx); //转两次
                _this.rotateImg(that, w, h, 'right', canvas, ctx);
                break;
            }
          } else {
            ctx.drawImage(that, 0, 0, w, h);
          }
          // 压缩图像质量
          var base64 = canvas.toDataURL('image/jpeg', obj.quality);
          // 回调函数返回base64的值
          callback(base64);
        }
    
      }
    
      getObjectURL(file) {
        var url = null;
        if (window.createObjectURL != undefined) {
          url = window.createObjectURL(file);
        } else if (window.URL != undefined) { // mozilla(firefox)
          url = window.URL.createObjectURL(file);
        } else if (window.webkitURL != undefined) { // webkit or chrome
          url = window.webkitURL.createObjectURL(file);
        }
        return url;
      }
    
    
      rotateImg(img, w, h, direction, canvas, ctx) {
        //最小与最大旋转方向,图片旋转4次后回到原方向
        var min_step = 0;
        var max_step = 3;
        //var img = document.getElementById(pid);
        if (img == null) return;
        //img的高度和宽度不能在img元素隐藏后获取,否则会出错
        var height = h;
        var width = w;
        //var step = img.getAttribute('step');
        var step = 2;
        if (step == null) {
          step = min_step;
        }
        if (direction == 'right') {
          step++;
          //旋转到原位置,即超过最大值
          step > max_step && (step = min_step);
        } else {
          step--;
          step < min_step && (step = max_step);
        }
        //旋转角度以弧度值为参数
        var degree = step * 90 * Math.PI / 180;
        // var ctx = canvas.getContext('2d');
        // alert(h)
        switch (step) {
          case 0:
            canvas.width = width;
            canvas.height = height;
            ctx.drawImage(img, 0, 0);
            break;
          case 1:
            canvas.width = height;
            canvas.height = width;
            ctx.rotate(degree);
            ctx.drawImage(img, 0, -height,w,h);
            break;
          case 2:
            canvas.width = width;
            canvas.height = height;
            ctx.rotate(degree);
            ctx.drawImage(img, -width, -height,w,h);
            break;
          case 3:
            canvas.width = height;
            canvas.height = width;
            ctx.rotate(degree);
            ctx.drawImage(img, -width, 0,w,h);
            break;
        }
      }
    
      ajaxThen(data) {
        return new Promise((resolve, reject) => {
          var form = new FormData();
          form.append('image', data);
          // console.log(data,form)
          $.ajax({
            url: '/home/image',
            data: form,
            method: 'post',
            dataType: 'json',
            contentType: false,
            processData: false,
            mimeType: "multipart/form-data",
            success: function(res) {
              resolve(res)
            }
          })
        })
    
      }
    
      getOrientation(file) {
        return new Promise((resolve, reject) => {
          EXIF.getData(file, () => {
            let o = EXIF.getTag(file, "Orientation");
            resolve(o);
            reject(o);
          })
        })
      }
    }
    
  • 相关阅读:
    基于微软解决方案的负载测试实现知识库1____(转)理解.NET中的数据库连接池
    [转] Performance vs. load vs. stress testing _Grig Gheorghiu (翻译水平有限,如有错误请帮忙刊正)
    Bill Gates Centimillionaire and one poor man.
    VB Comwrapper 的实现
    使用接口作为返回值
    如何排查SQL死锁的错误?
    VC++动态链接库编程之DLL典型实例
    VC++动态链接库编程之DLL木马
    VC中获取窗口句柄的各种方法 .
    VC++动态链接库编程之MFC扩展 DLL
  • 原文地址:https://www.cnblogs.com/linxue/p/9665871.html
Copyright © 2011-2022 走看看