移动端 Vue+Vant 的Uploader 实现上传、压缩、旋转图片功能


Posted in Javascript onJune 10, 2019

面向百度开发

html

<van-uploader :after-read="onRead" accept="image/*">
    <img src="./icon_input_add.png" />
 </van-uploader>

js

data() {
    return {
      files: {
        name: "",
        type: ""
      },
      headerImage: null,
      picValue: null,
      upImgUrl,
    }
  },
  // 组件方法 获取 流
  async onRead(file) {
      // console.log(file);
      // console.log(file.file);
      this.files.name = file.file.name; // 获取文件名
      this.files.type = file.file.type; // 获取类型
      this.picValue = file.file; // 文件流
      this.imgPreview(this.picValue);
    },
    // 处理图片
    imgPreview(file) {
      let self = this;
      let Orientation;
      //去获取拍照时的信息,解决拍出来的照片旋转问题
      Exif.getData(file, function () {
        Orientation = Exif.getTag(this, "Orientation");
      });
      // 看支持不支持FileReader
      if (!file || !window.FileReader) return;
      if (/^image/.test(file.type)) {
        // 创建一个reader
        let reader = new FileReader();
        // 将图片2将转成 base64 格式
        reader.readAsDataURL(file);
        // 读取成功后的回调
        reader.onloadend = function () {
          // console.log(this.result);
          let result = this.result;
          let img = new Image();
          img.src = result;
          //判断图片是否大于500K,是就直接上传,反之压缩图片
          if (this.result.length <= 500 * 1024) {
            self.headerImage = this.result;
            self.postImg();
          } else {
            img.onload = function () {
              let data = self.compress(img, Orientation);
              self.headerImage = data;
              self.postImg();
            };
          }
        };
      }
    },
    // 压缩图片
    compress(img, Orientation) {
      let canvas = document.createElement("canvas");
      let ctx = canvas.getContext("2d");
      //瓦片canvas
      let tCanvas = document.createElement("canvas");
      let tctx = tCanvas.getContext("2d");
      // let initSize = img.src.length;
      let width = img.width;
      let height = img.height;
      //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
      let ratio;
      if ((ratio = (width * height) / 4000000) > 1) {
        // console.log("大于400万像素");
        ratio = Math.sqrt(ratio);
        width /= ratio;
        height /= ratio;
      } else {
        ratio = 1;
      }
      canvas.width = width;
      canvas.height = height;
      //    铺底色
      ctx.fillStyle = "#fff";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      //如果图片像素大于100万则使用瓦片绘制
      let count;
      if ((count = (width * height) / 1000000) > 1) {
        // console.log("超过100W像素");
        count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
        //      计算每块瓦片的宽和高
        let nw = ~~(width / count);
        let nh = ~~(height / count);
        tCanvas.width = nw;
        tCanvas.height = nh;
        for (let i = 0; i < count; i++) {
          for (let j = 0; j < count; j++) {
            tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
            ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
          }
        }
      } else {
        ctx.drawImage(img, 0, 0, width, height);
      }
      //修复ios上传图片的时候 被旋转的问题
      if (Orientation != "" && Orientation != 1) {
        switch (Orientation) {
          case 6: //需要顺时针(向左)90度旋转
            this.rotateImg(img, "left", canvas);
            break;
          case 8: //需要逆时针(向右)90度旋转
            this.rotateImg(img, "right", canvas);
            break;
          case 3: //需要180度旋转
            this.rotateImg(img, "right", canvas); //转两次
            this.rotateImg(img, "right", canvas);
            break;
        }
      }
      //进行最小压缩
      let ndata = canvas.toDataURL("image/jpeg", 0.1);
      tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
      return ndata;
    },
    // 旋转图片
    rotateImg(img, direction, canvas) {
      //最小与最大旋转方向,图片旋转4次后回到原方向
      const min_step = 0;
      const max_step = 3;
      if (img == null) return;
      //img的高度和宽度不能在img元素隐藏后获取,否则会出错
      let height = img.height;
      let width = img.width;
      let 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);
      }
      //旋转角度以弧度值为参数
      let degree = (step * 90 * Math.PI) / 180;
      let ctx = canvas.getContext("2d");
      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);
          break;
        case 2:
          canvas.width = width;
          canvas.height = height;
          ctx.rotate(degree);
          ctx.drawImage(img, -width, -height);
          break;
        case 3:
          canvas.width = height;
          canvas.height = width;
          ctx.rotate(degree);
          ctx.drawImage(img, -width, 0);
          break;
      }
    },
    //将base64转换为文件
    dataURLtoFile(dataurl) {
      var arr = dataurl.split(","),
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], this.files.name, {
        type: this.files.type
      });
    },
    //这里写接口 
    async postImg() {
      let file = this.dataURLtoFile(this.headerImage);
      let formData = new window.FormData();
      formData.append("file", file);
      toast_loding(this, "图片上传中···");
      try {
        let res = await util.ajax.post(this.upImgUrl, formData, {
          headers: {
            "Content-Type": "multipart/form-data"
          }
        });
      } catch (e) {
        console.log(e);
      }
    }

总结

以上所述是小编给大家介绍的移动端 Vue+Vant 的Uploader 实现上传、压缩、旋转图片功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢! 

Javascript 相关文章推荐
jBox 2.3基于jquery的最新多功能对话框插件 常见使用问题解答
Nov 10 Javascript
js中Image对象以及对其预加载处理示例
Nov 20 Javascript
jquery fancybox ie6不显示关闭按钮的解决办法
Dec 25 Javascript
node.js实现多图片上传实例
Jun 03 Javascript
jQuery实现跨域
Feb 03 Javascript
第六篇Bootstrap表格样式介绍
Jun 21 Javascript
RequireJS多页面应用实例分析
Jun 29 Javascript
PhotoSwipe异步动态加载图片方法
Aug 25 Javascript
Bootstrap表格制作代码
Mar 17 Javascript
js实现简易聊天对话框
Aug 17 Javascript
使用canvas进行图像编辑的实例
Aug 29 Javascript
vue 项目打包通过命令修改 vue-router 模式 修改 API 接口前缀
Jun 13 Javascript
利用百度echarts实现图表功能简单入门示例【附源码下载】
Jun 10 #Javascript
jquery操作checkbox的常用方法总结【附测试源码下载】
Jun 10 #jQuery
利用Electron简单撸一个Markdown编辑器的方法
Jun 10 #Javascript
js实现类似iphone的网页滑屏解锁功能示例【附源码下载】
Jun 10 #Javascript
基于jquery实现的tab选项卡功能示例【附源码下载】
Jun 10 #jQuery
对node通过fs模块判断文件是否是文件夹的实例讲解
Jun 10 #Javascript
Javascript数组方法reduce的妙用之处分享
Jun 10 #Javascript
You might like
PHP 清空varnish 缓存的详解(包括指定站点下的)
2013/06/20 PHP
Zend Framework教程之响应对象的封装Zend_Controller_Response实例详解
2016/03/07 PHP
PHP中empty,isset,is_null用法和区别
2017/02/19 PHP
PHP中单例模式的使用场景与使用方法讲解
2019/03/18 PHP
js将long日期格式转换为标准日期格式实现思路
2013/04/07 Javascript
让js弹出窗口居前显示的实现方法
2013/07/10 Javascript
Jquery封装tab自动切换效果的具体实现
2013/07/13 Javascript
通过js简单实现将一个文本内容转译成加密文本
2013/10/22 Javascript
JavaScript整除运算函数ceil和floor的区别分析
2015/04/14 Javascript
实例详解JSON数据格式及json格式数据域字符串相互转换
2016/01/07 Javascript
js调用webservice构造SOAP进行身份验证
2016/04/27 Javascript
微信小程序 教程之条件渲染
2016/10/18 Javascript
微信小程序-拍照或选择图片并上传文件
2017/01/06 Javascript
使用Promise链式调用解决多个异步回调的问题
2017/01/15 Javascript
Swiper 4.x 使用方法(移动端网站的内容触摸滑动)
2018/05/17 Javascript
手写Vue源码之数据劫持示例详解
2021/01/04 Vue.js
Python中title()方法的使用简介
2015/05/20 Python
python求平均数、方差、中位数的例子
2019/08/22 Python
Python Collatz序列实现过程解析
2019/10/12 Python
浅谈Python类中的self到底是干啥的
2019/11/11 Python
django使用xadmin的全局配置详解
2019/11/15 Python
基于Python把网站域名解析成ip地址
2020/05/25 Python
Wedgwood美国官网:英国骨瓷,精美礼品及家居装饰
2018/02/17 全球购物
法国高保真音响和家庭影院商店:Son Video
2019/04/26 全球购物
美国爆米花工厂:The Popcorn Factory
2019/09/14 全球购物
Everlast官网:拳击、综合格斗和健身相关的体育用品
2020/08/03 全球购物
会计自荐书
2013/12/02 职场文书
微型企业创业投资计划书
2014/01/10 职场文书
生产部岗位职责范文
2014/02/07 职场文书
小学生保护环境倡议书
2014/05/15 职场文书
祖国在我心中演讲稿200字
2014/08/28 职场文书
银行党的群众路线教育实践活动对照检查材料
2014/09/25 职场文书
工作经历证明书范文
2014/11/02 职场文书
导游带团欢迎词
2015/09/30 职场文书
eval(cmd)与eval($cmd)的区别与联系
2021/07/07 PHP
MySQL中的 inner join 和 left join的区别解析(小结果集驱动大结果集)
2023/05/08 MySQL