移动端 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 相关文章推荐
jsp+javascript打造级连菜单的实例代码
Jun 14 Javascript
关于Javascript作用域链的八点总结
Dec 06 Javascript
jquery实现点击消失的代码
Mar 03 Javascript
用JS在浏览器中创建下载文件
Mar 05 Javascript
异步安全加载javascript文件的方法
Jul 21 Javascript
jQuery实现的简单折叠菜单(折叠面板)效果代码
Sep 16 Javascript
Angular.js如何从PHP读取后台数据
Mar 24 Javascript
JavaScript实现经纬度转换成地址功能
Mar 28 Javascript
vuejs前后端数据交互之从后端请求数据的实例
Aug 11 Javascript
js中的reduce()函数讲解
Jan 18 Javascript
微信小程序实现一个简单swiper代码实例
Dec 30 Javascript
原生js实现表格循环滚动
Nov 24 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面试题附答案
2009/01/07 PHP
PHP 裁剪图片成固定大小代码方法
2009/09/09 PHP
php密码生成类实例
2014/09/24 PHP
PHP比你想象的好得多
2014/11/27 PHP
php的扩展写法总结
2019/05/14 PHP
2020最新版 PhpStudy V8.1版本下载安装使用详解
2020/10/30 PHP
PHP dirname简单使用代码实例
2020/11/13 PHP
javascript getElementsByTagName
2011/01/31 Javascript
JAVASCRIPT车架号识别/验证函数代码 汽车车架号验证程序
2012/01/08 Javascript
基于jQuery的遍历同id元素 并响应事件的代码
2012/06/14 Javascript
JQuery触发事件例如click
2013/09/11 Javascript
浏览器窗口加载和大小改变事件示例
2014/02/27 Javascript
调用jQuery滑出效果时闪烁的解决方法
2014/03/27 Javascript
《JavaScript DOM 编程艺术》读书笔记之JavaScript 图片库
2015/01/09 Javascript
jquery带动画效果幻灯片特效代码
2015/08/27 Javascript
探究JavaScript函数式编程的乐趣
2015/12/14 Javascript
使用html+js+css 实现页面轮播图效果(实例讲解)
2017/09/21 Javascript
如何将你的AngularJS1.x应用迁移至React的方法
2018/02/01 Javascript
angularjs通过过滤器返回超链接的方法
2018/10/26 Javascript
[02:20]DOTA2中文配音宣传片
2013/05/22 DOTA
Python time模块详解(常用函数实例讲解,非常好)
2014/04/24 Python
举例详解Python中的split()函数的使用方法
2015/04/07 Python
在Python中使用mechanize模块模拟浏览器功能
2015/05/05 Python
一个简单的python爬虫程序 爬取豆瓣热度Top100以内的电影信息
2018/04/17 Python
python可视化实现代码
2019/01/15 Python
利用python-pypcap抓取带VLAN标签的数据包方法
2019/07/23 Python
python dict乱码如何解决
2020/06/07 Python
HTML5印章绘制电子签章图片(中文英文椭圆章、中文英文椭圆印章)
2019/06/03 HTML / CSS
国际礼品店:GiftsnIdeas
2018/05/03 全球购物
JSF界面控制层技术
2013/06/17 面试题
将相和教学反思
2014/02/04 职场文书
环境工程专业毕业生求职信
2014/09/30 职场文书
2014年度安全工作总结
2014/12/04 职场文书
护士求职自荐信
2015/03/25 职场文书
借条格式范本
2015/05/25 职场文书
2015年公司国庆放假通知
2015/07/30 职场文书