Vue.js 2.0 移动端拍照压缩图片上传预览功能


Posted in Javascript onMarch 06, 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] :这个参数允许忽略。

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

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

then(rst):

    rst.formData 后端可处理的数据;
    rst.file 压缩后的file对象(默认已经丢在rst.formData有一份了),需要注意的是如果压缩率太低的话,这个会是原始的file对象;
    rst.fileLen 生成后的图片的大小,后端可以通过此值来校验是否传输完整;
    rst.base64 生成后的图片base64,后端可以处理此字符串为图片,也直接用于img.src = base64;
    rst.base64Len 生成后的base64的大小,后端可以通过此值来校验是否传输完整 (如果采用base64上传方式);
    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字符串处理成图片时,需要将特殊字符过滤掉。

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);
   }
  }

以上所述是小编给大家介绍的Vue.js 2.0 移动端拍照压缩图片上传预览功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js获取日期:昨天今天和明天、后天
Jun 11 Javascript
node.js中的fs.futimesSync方法使用说明
Dec 17 Javascript
javascript实现点击商品列表checkbox实时统计金额的方法
May 15 Javascript
Bootstrap CSS布局之表格
Dec 17 Javascript
cocos creator Touch事件应用(触控选择多个子节点的实例)
Sep 10 Javascript
详解webpack性能优化——DLL
Oct 20 Javascript
vue自动化表单实例分析
May 06 Javascript
详解jQuery中的getAll()和cleanData()
Apr 15 jQuery
一百行JS代码实现一个校验工具
Apr 30 Javascript
浅谈vue限制文本框输入数字的正确姿势
Sep 02 Javascript
Vue.js仿Select下拉框效果
Feb 18 Javascript
vue 使用rules对表单字段进行校验的步骤
Dec 25 Vue.js
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
Bootstrap输入框组件简单实现代码
Mar 06 #Javascript
原生JS实现圣旨卷轴展开效果
Mar 06 #Javascript
You might like
改写ThinkPHP的U方法使其路由下分页正常
2014/07/02 PHP
php实现用已经过去多长时间的方式显示时间
2015/06/05 PHP
JS中数组Array的用法示例介绍
2014/02/20 Javascript
jQuery中[attribute=value]选择器用法实例
2014/12/31 Javascript
javascript限制文本框输入值类型的方法
2015/05/07 Javascript
jQuery实现的类似淘宝网站搜索框样式代码分享
2015/08/24 Javascript
Bootstrap每天必学之缩略图与警示窗
2015/11/29 Javascript
js字符串截取函数slice、substring和substr的比较
2016/05/17 Javascript
BootStrap入门教程(一)之可视化布局
2016/09/19 Javascript
Angular.js中angular-ui-router的简单实践
2017/07/18 Javascript
基于react组件之间的参数传递(详解)
2017/09/05 Javascript
js中bool值的转换及“&amp;&amp;”、“||”、 “!!”详解
2017/12/21 Javascript
vue slot 在子组件中显示父组件传递的模板
2018/03/02 Javascript
javaScript产生随机数的用法小结
2018/04/21 Javascript
解决layui-table单元格设置为百分比在ie8下不能自适应的问题
2019/09/28 Javascript
vue中使用rem布局代码详解
2019/10/30 Javascript
jQuery开发仿QQ版音乐播放器
2020/07/10 jQuery
python常用函数详解
2016/09/13 Python
对python同一个文件夹里面不同.py文件的交叉引用方法详解
2018/12/15 Python
python的pytest框架之命令行参数详解(上)
2019/06/27 Python
python抓取多种类型的页面方法实例
2019/11/20 Python
Django中和时区相关的安全问题详解
2020/10/12 Python
python+opencv实现车道线检测
2021/02/19 Python
使用css3背景渐变中的透明度来设置不同颜色的背景渐变
2014/03/31 HTML / CSS
极简的HTML5模版
2015/07/09 HTML / CSS
澳大利亚儿童和婴儿产品在线商店:Lime Tree Kids
2017/10/05 全球购物
PAUL HEWITT手表美国站:德国北部时尚生活配饰品牌,船锚元素
2017/11/18 全球购物
.NET程序员的几道面试题
2012/06/01 面试题
千元咖啡店的创业计划书范文
2013/12/29 职场文书
售后服务承诺书范文
2014/03/26 职场文书
遵纪守法演讲稿
2014/05/23 职场文书
刑事和解协议书范本
2014/11/19 职场文书
委托书格式要求
2015/01/28 职场文书
TensorFlow的自动求导原理分析
2021/05/26 Python
利用python调用摄像头的实例分析
2021/06/07 Python
Java实现贪吃蛇游戏的示例代码
2022/09/23 Java/Android