vuejs开发组件分享之H5图片上传、压缩及拍照旋转的问题处理


Posted in Javascript onMarch 06, 2017

一、前言

三年.net开发转前端已经四个月了,前端主要用webpack+vue,由于后端转过来的,前端不够系统,希望分享下开发心得与园友一起学习。

图片的上传之前都是用的插件(ajaxupload),或者传统上传图片的方式,各有利弊:插件的问题是依赖jq并且会使系统比较臃肿,还有传统的web开发模式 前后端偶尔在一起及对用户体验要求低,现在公司采用webpack+vue+restfullApi开发模式 前后端完全分离,遵从高内聚,低偶尔的原则,开发人员各司其职,一则提升开发效率(从长期来看,短期对于很多开发人员需要有个适应的过程,特别是初中级的前端处理业务逻辑方面的能力比较欠缺),二则提升用户体验。今天分享下在项目开发中写的的图片上传 vue组件。

二、处理问题

这里用h5做图片上传考虑到浏览器支持的问题,这里考虑的场景是在做webapp的时候

1.移动web图片上传还包括拍摄上传,但是在移动端会出现拍摄的照片会旋转,处理这个问题需要得到图片旋转的情况,可以用exif.js来获取,具体可以参看文档

2.图片压缩

3.旋转

三、代码

1组件代码

<template>
 <div>
  <input type="file" style="display: none;" id="img-upload" multiple accept="image/*" @change="uploadImg($event)"/>
 </div>
</template>
<script>
 import EXIF from '../../../Resource/Global/Js/exif'
 export default{
  name:"image-html5-upload",
  props:{
   imgArr:{
    type:Array,
    twoWay: true,
    default:Array
   },
   imgNumLimit:{//一次最多可以上传多少张照片
    type:Number,
    default:4
   }
  },
  methods:{
   "uploadImg": function(e){
    let tag = e.target;
    let fileList = tag.files;
    let imgNum = fileList.length;
    let _this = this;
    _this.imgArr = [];//图片数据清零
    if(this.imgArr.length + imgNum > this.imgNumLimit){
     alert('一次最多上传'+this.imgNumLimit+'张图片!');
     return;
    }
    var Orientation;
    for(let i=0;i<imgNum;i++){
     EXIF.getData(fileList[i], function(){
      Orientation = EXIF.getTag(fileList[i], 'Orientation');
     });
     let reader = new FileReader();
     reader.readAsDataURL(fileList[i]);
     reader.onload = function(){
      var oReader = new FileReader();
      oReader.onload = function(e) {
       var image = new Image();
       image.src = e.target.result;
       image.onload = function() {
        var expectWidth = this.naturalWidth;
        var expectHeight = this.naturalHeight;
        if (this.naturalWidth > this.naturalHeight && this.naturalWidth > 800) {
         expectWidth = 800;
         expectHeight = expectWidth * this.naturalHeight / this.naturalWidth;
        } else if (this.naturalHeight > this.naturalWidth && this.naturalHeight > 1200) {
         expectHeight = 1200;
         expectWidth = expectHeight * this.naturalWidth / this.naturalHeight;
        }
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        canvas.width = expectWidth;
        canvas.height = expectHeight;
        ctx.drawImage(this, 0, 0, expectWidth, expectHeight);
        var base64 = null;
        //修复ios上传图片的时候 被旋转的问题
        if(Orientation != "" && Orientation != 1){
         switch(Orientation){
          case 6://需要顺时针(向左)90度旋转
           _this.rotateImg(this,'left',canvas);
           break;
          case 8://需要逆时针(向右)90度旋转
           _this.rotateImg(this,'right',canvas);
           break;
          case 3://需要180度旋转
           _this.rotateImg(this,'right',canvas);//转两次
           _this.rotateImg(this,'right',canvas);
           break;
         }
        }
        base64 = canvas.toDataURL("image/jpeg", 0.8);
        if(fileList[i].size / 1024000 > 1){
         _this.imgScale(base64, 4)
        }else{
         _this.imgArr.push({"src": base64});
        }
        console.log(JSON.stringify(_this.imgArr));
       };
      };
      oReader.readAsDataURL(fileList[i]);
     }
    }
   },
   "imgScale": function(imgUrl,quality){
    let img = new Image();
    let _this = this;
    let canvas = document.createElement('canvas');
    let cxt = canvas.getContext('2d');
    img.src = imgUrl;
    img.onload = function(){
     //缩放后图片的宽高
     let width = img.naturalWidth/quality;
     let height = img.naturalHeight/quality;
     canvas.width = width;
     canvas.height = height;
     cxt.drawImage(this, 0, 0, width, height);
     _this.imgArr.push({"src": canvas.toDataURL('image/jpeg')});
    }
   },
   "rotateImg":function (img, direction,canvas) {//图片旋转
    var min_step = 0;
    var max_step = 3;
    if (img == null)return;
    var height = img.height;
    var width = img.width;
    var 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);
    }
    var degree = step * 90 * Math.PI / 180;
    var 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;
    }
   }
  }
 }
</script>

2.使用方法

<template>
 <div>
  <div class="album-img-list">
   <ul>
    <li v-for="img in imgList"><div class="album-bg-img"><img :src='img.src'> </div></li>
   </ul>
  </div>
  <div class="album">
   <label for="img-upload">上传照片</label>
    <image-html5-upload :img-arr.sync="imgList"></image-html5-upload>
  </div>
 </div>
</template>

以上所述是小编给大家介绍的vuejs开发组件分享之H5图片上传、压缩及拍照旋转的问题处理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jquery图片延迟加载 前端开发技能必备系列
Jun 18 Javascript
jQuery仿360导航页图标拖动排序效果代码分享
Aug 24 Javascript
javascript性能优化之DOM交互操作实例分析
Dec 12 Javascript
常见的javascript跨域通信方法
Dec 31 Javascript
AngularJs定制样式插入到ueditor中的问题小结
Aug 01 Javascript
Bootstrap实现圆角、圆形头像和响应式图片
Dec 14 Javascript
vue组件学习教程
Sep 09 Javascript
Vue.js的复用组件开发流程完整记录
Nov 29 Javascript
[jQuery] 事件和动画详解
Mar 05 jQuery
vue 点击展开显示更多(点击收起部分隐藏)
Apr 09 Javascript
JS使用new操作符创建对象的方法分析
May 30 Javascript
JS实现斐波那契数列的五种方式(小结)
Sep 09 Javascript
js正则表达式验证表单【完整版】
Mar 06 #Javascript
Vue.js 2.0 移动端拍照压缩图片上传预览功能
Mar 06 #Javascript
js实现动态显示时间效果
Mar 06 #Javascript
jQuery实现 上升、下降、删除、添加一行代码
Mar 06 #Javascript
Node.js使用NodeMailer发送邮件实例代码
Mar 06 #Javascript
js eval函数使用,js对象和字符串互转实例
Mar 06 #Javascript
js实现4个方向滚动的球
Mar 06 #Javascript
You might like
如何利用php+mysql保存和输出文件
2006/10/09 PHP
PHP register_shutdown_function函数的深入解析
2013/06/03 PHP
php命令行用法入门实例教程
2014/10/27 PHP
PHP中多线程的两个实现方法
2016/10/14 PHP
js关闭模态窗口刷新父页面或跳转页面
2012/12/13 Javascript
jQuery实现响应浏览器缩放大小并改变背景颜色
2014/10/31 Javascript
JavaScript中的null和undefined区别介绍
2015/01/01 Javascript
Spring mvc 接收json对象
2015/12/10 Javascript
前端框架Vue.js中Directive知识详解
2016/09/12 Javascript
详解React开发中使用require.ensure()按需加载ES6组件
2017/05/12 Javascript
JS实现快速比较两个字符串中包含有相同数字的方法
2017/09/11 Javascript
vue绑定的点击事件阻止冒泡的实例
2018/02/08 Javascript
react native 获取地理位置的方法示例
2018/08/28 Javascript
Vue状态模式实现窗口停靠功能(灵动、自由, 管理后台Admin界面)
2020/03/06 Javascript
一文秒懂nodejs中的异步编程
2021/01/28 NodeJs
python 获取list特定元素下标的实例讲解
2018/04/09 Python
python 判断网络连通的实现方法
2018/04/22 Python
通过Pandas读取大文件的实例
2018/06/07 Python
python中的socket实现ftp客户端和服务器收发文件及md5加密文件
2020/04/01 Python
完美解决pyinstaller打包报错找不到依赖pypiwin32或pywin32-ctypes的错误
2020/04/01 Python
python 识别登录验证码图片功能的实现代码(完整代码)
2020/07/03 Python
Python实现我的世界小游戏源代码
2021/03/02 Python
伦敦剧院及景点门票:Encore Tickets
2018/07/01 全球购物
Stutterheim瑞典:瑞典高级外套时装品牌
2019/06/24 全球购物
德国购买门票网站:ADticket.de
2019/10/31 全球购物
大学毕业生通用求职信
2013/09/28 职场文书
婚纱摄影师求职信范文
2014/04/17 职场文书
建筑投标担保书
2014/05/20 职场文书
关于环保的标语
2014/06/13 职场文书
2014年个人师德工作总结
2014/12/04 职场文书
会计试用期自我评价
2015/03/10 职场文书
MySQL pt-slave-restart工具的使用简介
2021/04/07 MySQL
vue3中provide && inject的使用
2021/07/01 Vue.js
redis的list数据类型相关命令介绍及使用
2022/01/18 Redis
JavaScript中的LHS和RHS分析详情
2022/04/06 Javascript
nginx访问报403错误的几种情况详解
2022/07/23 Servers