移动端 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 实现的自定义对话框
Mar 24 Javascript
JavaScript调试工具汇总
Dec 23 Javascript
JavaScript学习笔记之ES6数组方法
Mar 25 Javascript
浅谈js中的延迟执行和定时执行
May 31 Javascript
jQuery实现判断控件是否显示的方法
Jan 11 Javascript
微信小程序实现图片自适应(支持多图)
Jan 25 Javascript
javascript 正则表达式分组、断言详解
Apr 20 Javascript
jQuery插件artDialog.js使用与关闭方法示例
Oct 09 jQuery
浅谈如何使用 webpack 优化资源
Oct 20 Javascript
小程序实现列表多个批量倒计时
Jan 29 Javascript
微信小程序自定义可滑动顶部TabBar选项卡实现页面切换功能示例
May 14 Javascript
jQuery实现视频展示效果
May 30 jQuery
利用百度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
一个简单的自动发送邮件系统(三)
2006/10/09 PHP
php 生成静态页面的办法与实现代码详细版
2010/02/15 PHP
PHP错误Cannot use object of type stdClass as array in错误的解决办法
2014/06/12 PHP
php返回当前日期或者指定日期是周几
2015/05/21 PHP
PHP ADODB实现分页功能简单示例
2018/05/25 PHP
PHP调用接口用post方法传送json数据的实例
2018/05/31 PHP
laravel配置Redis多个库的实现方法
2019/04/10 PHP
KindEditor在php环境下上传图片功能集成的方法示例
2020/07/20 PHP
Jquery chosen动态设置值实例介绍
2013/08/08 Javascript
Jquery 模拟用户点击超链接或者按钮的方法
2013/10/25 Javascript
基于jquery实现弹幕效果
2016/09/29 Javascript
localStorage的黑科技-js和css缓存机制
2017/02/06 Javascript
jquery.guide.js新版上线操作向导镂空提示jQuery插件(推荐)
2017/05/20 jQuery
详解开源的JavaScript插件化框架MinimaJS
2017/10/26 Javascript
vue axios 给生产环境和发布环境配置不同的接口地址(推荐)
2018/05/08 Javascript
Vue2.0生命周期的理解
2018/08/20 Javascript
vue 搭建后台系统模块化开发详解
2019/05/01 Javascript
Python实现的二维码生成小软件
2014/07/11 Python
解决Matplotlib图表不能在Pycharm中显示的问题
2018/05/24 Python
python批量修改图片大小的方法
2018/07/24 Python
python 获取一个值在某个区间的指定倍数的值方法
2018/11/12 Python
Python+PyQt5实现美剧爬虫可视工具的方法
2019/04/25 Python
python安装pil库方法及代码
2019/06/25 Python
关于阿里云oss获取sts凭证 app直传 python的实例
2019/08/20 Python
解决Pytorch训练过程中loss不下降的问题
2020/01/02 Python
python爬虫如何解决图片验证码
2021/02/14 Python
英国设计师泳装、沙滩装和比基尼在线精品店:Beach Cafe
2019/08/28 全球购物
综合实践活动方案
2014/02/14 职场文书
演讲稿祖国在我心中
2014/05/04 职场文书
授权委托书
2014/07/31 职场文书
乡镇党建工作汇报材料
2014/10/27 职场文书
婚宴祝酒词大全
2015/08/10 职场文书
八年级历史教学反思
2016/02/19 职场文书
2016民族团结先进个人事迹材料
2016/02/26 职场文书
总结python多进程multiprocessing的相关知识
2021/06/29 Python
bootstrapv4轮播图去除两侧阴影及线框的方法
2022/02/15 HTML / CSS