移动端 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 相关文章推荐
jquery tab插件精简版分享
Sep 10 Javascript
js调用浏览器打印模块实现点击按钮触发自定义函数
Mar 21 Javascript
使用jQuery仿苹果官网焦点图特效
Dec 23 Javascript
jquery实现仿新浪微博评论滚动效果
Aug 06 Javascript
Bootstrap打造一个左侧折叠菜单的系统模板(二)
May 17 Javascript
JavaScript判断页面加载完之后再执行预定函数的技巧
May 17 Javascript
JSP基于Bootstrap分页显示实例解析
Jun 12 Javascript
关于javascript的一些知识以及循环详解
Sep 12 Javascript
详解Angular 4 表单快速入门
Jun 05 Javascript
浅谈Vuex的状态管理(全家桶)
Nov 04 Javascript
vue组件父与子通信详解(一)
Nov 07 Javascript
详解组件库的webpack构建速度优化
Jun 18 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的array_multisort()使用方法介绍
2012/05/16 PHP
关于PHP堆栈与列队的学习
2013/06/21 PHP
PHP实现事件机制的方法
2015/07/10 PHP
php getcwd与dirname(__FILE__)区别详解
2016/09/24 PHP
thinkphp5 URL和路由的功能详解与实例
2017/12/26 PHP
轻轻松松学JS调试(不下载任何工具)
2010/04/14 Javascript
深入理解JavaScript系列(11) 执行上下文(Execution Contexts)
2012/01/15 Javascript
js鼠标滑过弹出层的定位IE6bug解决办法
2012/12/26 Javascript
使用JS CSS去除IE链接虚线框的三种方法
2013/11/14 Javascript
javascript利用apply和arguments复用方法
2013/11/25 Javascript
setTimeout自动触发一个js的方法
2014/01/15 Javascript
jquery ajax跨域解决方法(json方式)
2014/02/04 Javascript
jquery跟js初始化加载的多种方法及区别介绍
2014/04/02 Javascript
jQuery通过改变input的type属性实现密码显示隐藏切换功能
2017/02/08 Javascript
Bootstrap面板学习使用
2017/02/09 Javascript
微信小程序 开发之顶部导航栏实例代码
2017/02/23 Javascript
原生JS实现的自动轮播图功能详解
2018/12/28 Javascript
JS操作json对象key、value的常用方法分析
2019/10/29 Javascript
js实现简单进度条效果
2020/03/25 Javascript
Openlayers测量距离与面积的实现方法
2020/09/25 Javascript
Python自动连接ssh的方法
2015/03/07 Python
深入理解Python3中的http.client模块
2017/03/29 Python
分享一下如何编写高效且优雅的 Python 代码
2017/09/07 Python
详解Python3的TFTP文件传输
2018/06/26 Python
python 移除字符串尾部的数字方法
2018/07/17 Python
python 多线程中子线程和主线程相互通信方法
2018/11/09 Python
python range实例用法分享
2020/02/06 Python
浅谈Tensorflow加载Vgg预训练模型的几个注意事项
2020/05/26 Python
Python的logging模块基本用法
2020/12/24 Python
危货运输企业安全生产责任书
2014/07/28 职场文书
公司领导班子对照检查材料
2014/09/24 职场文书
2015年档案管理工作总结
2015/04/08 职场文书
2015年出纳年终工作总结
2015/05/14 职场文书
费用申请报告范文
2015/05/15 职场文书
2019年销售人员的职业生涯规划书
2019/03/25 职场文书
同学聚会开幕词
2019/04/02 职场文书