Vue.js 2.0 移动端拍照压缩图片预览及上传实例


Posted in Javascript onApril 27, 2017

在学习和使用Vue.js 2.0 的过程中遇到不少不一样的地方,本来移动端开发H5应用,准备将mui框架和Vue.js+vue-router+vuex 全家桶结合起来使用,但是在拍照上传的实现过程中遇到了无法调用plus的H5+接口的问题,所以最后拍照上传功能还是使用input file方式里解决的。但是内心还是不甘心的,由于项目进度推进,迭代版本,所以不得不放弃,后续可能我将此功能使用调用H5+接口实现。

首先我来讲我实现这个拍照预览压缩上传的思路,准确的说应该是拍照或选择图片压缩之后预览及上传这个流程。每次拍照或选择一张图片-然后压缩图片-预览上传。上传图片压缩插件是localResizeIMG , 这个插件的使用说明可以去看wiki,基本原理是通过canvas渲染图片,再通过 toDataURL 方法压缩保存为base64字符串(能够编译为jpg格式的图片),压缩效果很不错,ios拍照2MB多压缩下来大概是60-80kb左右,失真不是太严重,但是对我的项目来说图片清晰可见就好,我贴的代码里面也会有使用的演示。

<template>
 <h5 class="content-header">图片列表</h5>
 <div class="image-list">
 <div class="list-default-img" v-show="isPhoto" @click.stop="addPic">
  <img src="./images/icon_photo.png" />
  <span>请选择或者拍照上传照片</span>
  <input type="file" accept="image/jpeg,image/jpg,image/png" capture="camera" @change="onFileChange" style="display: none;">
 </div>
 <ul class="list-ul" v-show="!isPhoto">
  <li class="list-li" v-for="(iu, index) in imgUrls">
  <a class="list-link" @click='previewImage(iu)'>
   <img :src="iu">
  </a>
  <span class="list-img-close" @click='delImage(index)'></span>
  </li>
  <li class="list-li-add">
  <span class="add-img" @click.stop="addPic"></span>
  </li>
 </ul>
 </div>
  <div class="add-preview" v-show="isPreview" @click="closePreview">
 <img :src="previewImg">
 </div>
 
</template>

<script>

 export default {
 data: function () {
  return {
  imgUrls: [],
  urlArr: [],
  isPhoto: true,
  btnTitle: '',
  isModify: false,
  previewImg:'',
  isPreview: false
  }
 },
 watch: {
  imgUrls: 'toggleAddPic'
 },
 methods: {
  toggleAddPic: function() {
  let vm = this;
  if(vm.imgUrls.length >= 1) {
   vm.isPhoto = false;
  } else {
   vm.isPhoto = true;
  }
  },
  addPic: function(e) {
  let vm = this;
  $('input[type=file]').trigger('click');
  return false;
  },
  onFileChange: function(e) {
  var files = e.target.files || e.dataTransfer.files;
  if(!files.length) return;
  this.createImage(files, e);
  },
  createImage: function(file, e) {
  let vm = this;
  lrz(file[0], { width: 480 }).then(function(rst) {
   vm.imgUrls.push(rst.base64);
   return rst;
  }).always(function() {
  // 清空文件上传控件的值
  e.target.value = null;
  });
  },
  delImage: function(index) {
  let vm = this;
  let btnArray = ['取消', '确定'];
  mui.confirm('确定删除该图片?','提示', btnArray, function(e) {
   if (e.index == 1) {
   vm.imgUrls.splice(index, 1);
   }
  })

  },
  previewImage: function(url){
  let vm = this;
  vm.isPreview = true;
  vm.previewImg = url;
  },
  closePreview: function(){
  let vm = this;
  vm.isPreview = false;
  vm.previewImg = "";
  },
  saveImage: function(){
  let vm = this;
  let urlArr = [],
  imgUrls = this.imgUrls;

  for(let i = 0; i < imgUrls.length; i++) {
   if(imgUrls[i].indexOf('file') == -1) {
   urlArr.push(imgUrls[i].split(',')[1]);
   } else {
   urlArr.push(imgUrls[i]);
   }
  }

  //数据传输操作
  }
 }
 }
 
</script>

1.点击拍照或选择图片 addPic

在vue.js中出发拍照和选择图片是频繁操作行为,每次只能拍照或选择一张图片,可以拍多张上传,使用给click事件加上.stop的修饰符,.stop - 调用 event.stopPropagation() ,是为了停止冒泡。accept是为了规定通过文件上传来提交的文件的类型,capture是webApp中捕获到系统默认的设备,camera--照相机;camcorder--摄像机;microphone--录音。

Vue.js 2.0 移动端拍照压缩图片预览及上传实例   

在触发拍照行为的时候绑定change事件 onFileChange 获取file文件对象,然后调用lrz方法压缩图片,在imgUrls数组中添加基于base64格式的图片。

lrz(file[0], { width: 480 }).then(function(rst) {
   vm.imgUrls.push(rst.base64);
   return rst;
  }).always(function() {
  // 清空文件上传控件的值
  e.target.value = null;
  });
lrz(file, [options]);

file: 通过 input:file 得到的文件,或者直接传入图片路径。

[options] :这个参数允许忽略。

  1.     width {Number} 图片最大不超过的宽度,默认为原图宽度,高度不设时会适应宽度;
  2.     height {Number} 同上;
  3.     quality {Number} 图片压缩质量,取值 0 - 1,默认为0.7;
  4.     fieldName {String} 后端接收的字段名,默认:file;

返回结果是一个promise对象,有then()、catch()、always三个方法。

then(rst):

  1.     rst.formData 后端可处理的数据;
  2.     rst.file 压缩后的file对象(默认已经丢在rst.formData有一份了),需要注意的是如果压缩率太低的话,这个会是原始的file对象;
  3.     rst.fileLen 生成后的图片的大小,后端可以通过此值来校验是否传输完整;
  4.     rst.base64 生成后的图片base64,后端可以处理此字符串为图片,也直接用于img.src = base64;
  5.     rst.base64Len 生成后的base64的大小,后端可以通过此值来校验是否传输完整 (如果采用base64上传方式);
  6.     rst.origin 也就是原始的file对象,里面存了一些原始文件的信息,例如大小,日期等;

catch(err) 、always() 。

注意:由于我们可能持续点击拍照上传图片,使用在alway回调函数里面必须清空上传控制的值。

// 清空文件上传控件的值
 e.target.value = null;

2. 点击拍第一张照片和显示预览以及继续拍照的DOM显示  isPhoto

   默认 isPhoto 为true,隐藏继续拍照的DOM显示,toggleAddPic 监听当前选中imgUrls数组长度,转换 isPhoto 的布尔值若有一张及以上的图片设置 isPhoto 为false, 则隐藏点击拍第一张照片DOM,显示继续拍照的DOM;若没有图片,则隐藏继续拍照的DOM,显示击拍第一张照片DOM。

3. 删除已选择的压缩图片 delImage

根据数组对应的下标,在imgUrls中删除对应的图片数据。

delImage: function(index) {
  let vm = this;
  let btnArray = ['取消', '确定'];
  mui.confirm('确定删除该图片?','提示', btnArray, function(e) {
   if (e.index == 1) {
   vm.imgUrls.splice(index, 1);
   }
  })

  }

Vue.js 2.0 移动端拍照压缩图片预览及上传实例

4. 大图预览已经被压缩的图片及关闭大图预览  isPreview previewImage closePreview

在这里大图预览就是将base64格式的图片直接放进预览DOM的img src中放大展示,点击图片自身关闭预览,清空img src资源。

Vue.js 2.0 移动端拍照压缩图片预览及上传实例

5. 对base64图片传输前的处理 saveImage

saveImage: function(){
  let vm = this;
  let urlArr = [],
  imgUrls = this.imgUrls;

  for(let i = 0; i < imgUrls.length; i++) {
   if(imgUrls[i].indexOf('file') == -1) {
   urlArr.push(imgUrls[i].split(',')[1]);
   } else {
   urlArr.push(imgUrls[i]);
   }
  }

  //数据传输操作
  }

我压缩成base64字符串是“data:image/jpeg;base64,~~”的字符串,为了后端好处理,我这里为了将编辑时候后台返回的图片url区别开来,将“data:image/jpeg;base64,"截取掉,只传递给后端逗号后面的base64字符串。

注意:后端接收到我传递的base64字符串数组的时候,发现字符经如果被urlencode后标准的base64中的/、 +会被转成%xx,后端在将base64字符串处理成图片时,需要将特殊字符过滤掉。

[HttpPost]
    public ActionResult MUploadImgBase64Str(string base64str)
    {
      try
      {
        var imgData = base64str;
        //过滤特殊字符即可  
        string dummyData = imgData.Trim().Replace("%", "").Replace(",", "").Replace(" ", "+");
        if (dummyData.Length % 4 > 0)
        {
          dummyData = dummyData.PadRight(dummyData.Length + 4 - dummyData.Length % 4, '=');
        }
        byte[] byteArray = Convert.FromBase64String(dummyData);
        using (System.IO.MemoryStream ms = new System.IO.MemoryStream(byteArray))
        {
          var img = System.Drawing.Image.FromStream(ms);

          var path = "~/Content/UploadFiles/mobile/";
          var uploadpath = Server.MapPath(path);
          if (!Directory.Exists(uploadpath))
          {
            Directory.CreateDirectory(uploadpath);
          }
          var saveName = uploadpath + “stoneniqiu” + ".jpg";
          img.Save(saveName);
          return Json(saveName);
        }
      }
      catch (Exception e)
      {
        return Json(e.Message);

      }
    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
如何用javascript去掉字符串里的所有空格
Feb 08 Javascript
js 格式化时间日期函数小结
Mar 20 Javascript
jQuery+jRange实现滑动选取数值范围特效
Mar 14 Javascript
JS根据生日算年龄的方法
May 05 Javascript
Javascript数组循环遍历之forEach详解
Nov 07 Javascript
微信小程序与php 实现微信支付的简单实例
Jun 23 Javascript
ionic 自定义弹框效果
Jun 27 Javascript
详解利用Angular实现多团队模块化SPA开发框架
Nov 27 Javascript
详解webpack 打包文件体积过大解决方案(code splitting)
Apr 10 Javascript
解决使用bootstrap的dropdown部件时报错:error:Bootstrap dropdown require Popper.js问题
Aug 30 Javascript
Vue退出登录时清空缓存的实现
Nov 12 Javascript
uniapp与webview之间的相互传值的实现
Jun 29 Javascript
微信小程序 实现动态显示和隐藏某个控件
Apr 27 #Javascript
JS ES6中setTimeout函数的执行上下文示例
Apr 27 #Javascript
Vue实现购物车功能
Apr 27 #Javascript
js轮播图透明度切换(带上下页和底部圆点切换)
Apr 27 #Javascript
Angular.js中定时器循环的3种方法总结
Apr 27 #Javascript
浅谈js使用in和hasOwnProperty获取对象属性的区别
Apr 27 #Javascript
微信小程序 wx:for的使用实例详解
Apr 27 #Javascript
You might like
PHP 处理图片的类实现代码
2009/10/23 PHP
php 多关键字 高亮显示实现代码
2012/04/23 PHP
关于PHP递归算法和应用方法介绍
2013/04/15 PHP
PHP mail()函数使用及配置方法
2014/01/14 PHP
thinkphp中AJAX返回ajaxReturn()方法分析
2016/12/06 PHP
Javascript Tab 导航插件 (23个)
2009/06/11 Javascript
火狐下input焦点无法重复获取问题的解决方法
2014/06/16 Javascript
JavaScript代码复用模式详解
2014/11/07 Javascript
基于jQuery实现仿百度首页换肤背景图片切换代码
2015/08/25 Javascript
Three.js学习之Lamber材质和Phong材质
2016/08/04 Javascript
js 监控iframe URL的变化实例代码
2017/07/12 Javascript
vue.js在标签属性中插入变量参数的方法
2018/03/06 Javascript
解决vue中post方式提交数据后台无法接收的问题
2018/08/11 Javascript
JavaScript基础教程之如何实现一个简单的promise
2018/09/11 Javascript
详解使用React.memo()来优化函数组件的性能
2019/03/19 Javascript
基于JavaScript实现表格隔行换色
2020/05/08 Javascript
vue自定义树状结构图的实现方法
2020/10/18 Javascript
python网络编程学习笔记(10):webpy框架
2014/06/09 Python
python获取本地计算机名字的方法
2015/04/29 Python
python根据文章标题内容自动生成摘要的实例
2019/02/21 Python
python base64库给用户名或密码加密的流程
2020/01/02 Python
pytorch 自定义参数不更新方式
2020/01/06 Python
python中如何写类
2020/06/29 Python
PyTorch预训练Bert模型的示例
2020/11/17 Python
浅谈Selenium+Webdriver 常用的元素定位方式
2021/01/13 Python
HTML5之SVG 2D入门8—文档结构及相关元素总结
2013/01/30 HTML / CSS
Aerosoles爱柔仕官网:美国舒软女鞋品牌
2017/07/17 全球购物
CSS代码检查工具stylelint的使用方法详解
2021/03/27 HTML / CSS
应届护士推荐信
2013/11/16 职场文书
2014年教师培训的自我评价
2014/01/03 职场文书
优秀食品类广告词
2014/03/19 职场文书
写得不错的求职信范文
2014/07/11 职场文书
作风建设整改方案
2014/10/27 职场文书
新人入职感言
2015/07/31 职场文书
浅谈resultMap的用法及关联结果集映射
2021/06/30 Java/Android
WCG2010 星际争霸决赛 Flash vs Goojila 1 星际经典比赛回顾
2022/04/01 星际争霸