移动端 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 相关文章推荐
XML+XSL 与 HTML 两种方案的结合
Apr 22 Javascript
加速IE的Javascript document输出的方法
Dec 02 Javascript
Android中资源文件(非代码部分)的使用概览
Dec 18 Javascript
通过JS自动隐藏手机浏览器的地址栏实现原理与代码
Jan 02 Javascript
javascript常用的正则表达式实例
May 15 Javascript
使用node.js 获取客户端信息代码分享
Nov 26 Javascript
使用FlexiGrid实现Extjs表格效果方法分享
Dec 16 Javascript
javascript中使用new与不使用实例化对象的区别
Jun 22 Javascript
浅谈jquery拼接字符串效率比较高的方法
Feb 22 Javascript
浅谈JavaScript中的属性:如何遍历属性
Sep 14 Javascript
JS实现的文字间歇循环滚动效果完整示例
Feb 13 Javascript
HTML+JavaScript实现扫雷小游戏
Sep 30 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
基于mysql的论坛(3)
2006/10/09 PHP
在PHP中运行Linux命令并启动SSH服务的例子
2014/06/12 PHP
网页自动跳转代码收集
2009/09/27 Javascript
解决IE下select标签innerHTML插入option的BUG(兼容IE,FF,Opera,Chrome,Safari)
2010/05/13 Javascript
Jquery的hide及toggle方法让超链接慢慢消失
2013/09/06 Javascript
javascript中对Attr(dom中属性)的操作示例讲解
2013/12/02 Javascript
jquery淡化版banner异步图片文字效果切换图片特效
2014/04/08 Javascript
JS实现网页上随机产生超链接地址的方法
2015/11/09 Javascript
jQuery EasyUi实战教程之布局篇
2016/01/26 Javascript
Bootstrap3制作自己的导航栏
2016/05/12 Javascript
Jq通过td获取同行其它列td的方法
2016/10/05 Javascript
Angular2中Bootstrap界面库ng-bootstrap详解
2016/10/18 Javascript
浅析JavaScript动画模拟拖拽原理
2016/12/09 Javascript
js实现淡入淡出轮播切换功能
2017/01/13 Javascript
深入nodejs中流(stream)的理解
2017/03/27 NodeJs
详解A标签中href=&quot;&quot;的几种用法
2017/08/20 Javascript
Node层模拟实现multipart表单的文件上传示例
2018/01/02 Javascript
vue根据值给予不同class的实例
2018/09/29 Javascript
JS实现的图片选择顺序切换和循环切换功能示例【测试可用】
2018/12/28 Javascript
Python 3.6 性能测试框架Locust安装及使用方法(详解)
2017/10/11 Python
详解Python nose单元测试框架的安装与使用
2017/12/20 Python
详解django中使用定时任务的方法
2018/09/27 Python
python3+selenium实现qq邮箱登陆并发送邮件功能
2019/01/23 Python
Python3.4学习笔记之类型判断,异常处理,终止程序操作小结
2019/03/01 Python
python+pyqt5实现图片批量缩放工具
2019/03/18 Python
Python进程的通信Queue、Pipe实例分析
2020/03/30 Python
python 负数取模运算实例
2020/06/03 Python
如何用Python 实现全连接神经网络(Multi-layer Perceptron)
2020/10/15 Python
CSS伪类与CSS伪元素的区别及由来具体说明
2012/12/07 HTML / CSS
奥斯汀独木舟和皮划艇:Austin Canoe & Kayak
2018/05/22 全球购物
会计人员演讲稿
2014/09/11 职场文书
人身损害赔偿协议书范本
2014/09/27 职场文书
工程安全生产协议书
2014/11/21 职场文书
2016暑期政治学习心得体会
2016/01/23 职场文书
如何在向量化NumPy数组上进行移动窗口
2021/05/18 Python
springboot使用Redis作缓存使用入门教程
2021/07/25 Redis