zoukankan      html  css  js  c++  java
  • webAPP如何实现移动端拍照上传(Vue组件示例)?

    摘要:使用HTML5编写移动Web应用,主要是为了尝试一下“一套代码多处运行”,一个webapp几乎可以不加修改的运行在PC/Android/iOS等上面运行。但是写到现在觉得虽然这种方式弊大于利,不仅在速度上有差异,webapp对移动端的一些原生功能支持并没有那么好。我用的vue写的系统,完成之后用webpack打包模块,hbuilder打包成apk,但是要解决的问题并不少。现在来说说webapp拍照上传。

    html5是支持拍照上传或者调用本地相册的,

    <!--兼容安卓微信调用摄像头-->
     <input type="file" name="file"  capture="camera">
    
    <!--兼容安卓默认选择sd卡上的相册图片-->
     <input type="file" name="file" accept="image/*" >

    然而hbuilder打包apk之后,在安卓机(华为荣耀9)测试的时候,发现  capture="camera" 失效了,打开的是本地相册,但是不能调用摄像头。我就打开了webpack-server,移动端的浏览器运行的时候,在浏览器里面是可以调用摄像头的,最后发现了很多人都有这个问题,但是并没有说明解决办法。我自己最后是结合H5提供的 window.plus 功能调用移动端的摄像头,当然,先判断移动端是否支持 window.plus ,如果不支持,就依然用 <input> 实现图片选取。

    H5 的 plus.camera 官方 API:http://www.html5plus.org/doc/zh_cn/camera.html

    下面我就说说我的解决方法,主要是参照了网上一些实例和官网API写出来的,请看下面的VUE组件,这个组件可以直接引用,有兴趣的同学可以试试:

      1 <template>
      2     <div>
      3         <div class="camera-photo" ref="divGenres" v-show="isPhoto" @click="choiceImg">
      4         <img style="300px;height:300px;" src="https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1528077222&di=69a2ffcffd12e35216ab71da7a610abe&src=http://img.zcool.cn/community/01f15555b4df7e6ac725ca50c172a1.png@2o.png"/>
      5         <br>
      6         <span>请选择图片上传</span>
      7         <input type="file" ref="uploadImage" @change="onFileChange" accept="image/*" capture="camera" style="display: none;">
      8       </div>
      9 
     10     <div class="list-li" v-show="show">
     11         <div style="display: inline-block;">
     12             <a class="list-link" @click='previewImage(imgsrc)'>
     13               <img :src="imgsrc">
     14             </a>
     15             <span class="list-img-close" @click='delImage'></span>
     16         </div>
     17         <div class="add-preview" v-show="isPreview" @click="closePreview">
     18           <img :src="previewImg">
     19         </div>
     20         <button type="button" class="upload-button" @click="upload">图片上传</button> 
     21       </div>
     22     </div>
     23 </template>
     24 
     25 <script>  
     26   import Bus from '../bus.js'
     27   import qs from "qs"
     28     export default {  
     29         data(){
     30             return{
     31                 imgsrc:'',//上传的·图片的地址
     32                 show:false,//图片放大预览
     33                 previewImg: '',//预览图片的地址
     34         isPreview: false,//是否预览当前图片
     35         isPhoto: true,
     36         uploadFile:null
     37             }
     38         },
     39         methods:{
     40 
     41       choiceImg(){
     42         let self = this;
     43         if (!window.plus){
     44             self.addPic()//如果不支持plus,就用本地相册上传即可
     45             return;
     46           }
     47 
     48         let title = "选择照片"
     49         let btns = ['拍照','相册']
     50 
     51         var func = function(e){  
     52           var index = e.index;  
     53 
     54           if(index == 1) self.choiceCamera();  
     55           if(index == 2) self.choicePic();  
     56         }
     57 
     58         if(title && btns && btns.length > 0){
     59           var btnArray = [];
     60           for(var i=0; i<btns.length; i++){
     61             btnArray.push({title:btns[i]});
     62           }
     63           
     64           plus.nativeUI.actionSheet({
     65             title : title,
     66             cancel : '取消',
     67             buttons : btnArray
     68           }, function(e){
     69             if(func) func(e);
     70           });
     71         }
     72       },
     73 
     74       choiceCamera(){ 
     75         let self = this;
     76         var cmr = plus.camera.getCamera();  
     77         cmr.captureImage(function (path){  
     78 
     79             plus.io.resolveLocalFileSystemURL(path, function(entry){
     80                   self.imgsrc= entry.toLocalURL();
     81                   self.show = true; 
     82  
     83             }, function(e){plus.nativeUI.toast("读取拍照文件错误:" + e.message);  });  
     84         }, function(e){},{index:1,filename:"_doc/camera/"});  
     85       } , 
     86 
     87       choicePic(){  
     88         let self = this;
     89          plus.gallery.pick( function(p){  
     90            plus.io.resolveLocalFileSystemURL(p, function(entry) { 
     91                   self.imgsrc= entry.toLocalURL();
     92                   self.show = true; 
     93           }, function(e) {  
     94               plus.nativeUI.toast("读取拍照文件错误:" + e.message);  
     95           });  
     96            }, function ( e ) {  plus.nativeUI.toast("读取拍照文件错误:" + e.message);}, {  
     97           filename: "_doc/camera/",  
     98           filter:"image"  
     99            } );  
    100       },
    101 
    102       upload(){
    103         var self = this
    104         var wt ;
    105         if (window.plus)
    106           wt = plus.nativeUI.showWaiting();
    107 
    108         var img = new Image,
    109             width = 512, //image resize   压缩后的宽
    110             quality = 0.5, //image quality  压缩质量
    111             canvas = document.createElement("canvas"),
    112             drawer = canvas.getContext("2d");
    113        img.src = self.imgsrc;
    114        img.onload = function(){//利用canvas压缩图片
    115        canvas.width = width;
    116        canvas.height = width * (img.height / img.width);
    117         drawer.drawImage(img, 0, 0, canvas.width, canvas.height);
    118         var base64 = canvas.toDataURL("image/*", quality); 
    119         var pic = base64.split(',')[1];//图片的base64编码内容
    120         var f=self.imgsrc;
    121         var filename=f.replace(f.substring(0, f.lastIndexOf('/') + 1), '');//图片名称
    122 
    123         if(self.uploadFile !== null){//addPic方法得到的图片文件
    124           filename =  self.uploadFile.name
    125           let reader = new FileReader();
    126           reader.readAsDataURL(self.uploadFile);
    127           reader.onload = function(e){
    128             img.src = e.target.result;
    129           }
    130          img.onload = function(){
    131          canvas.width = width;
    132          canvas.height = width * (img.height / img.width);
    133           drawer.drawImage(img, 0, 0, canvas.width, canvas.height);
    134           base64 = canvas.toDataURL("image/*", quality); 
    135           pic = base64.split(',')[1];
    136         }
    137         }
          //此处是将图片上传到服务器的代码,略过
    138 } 139 }, 140 141 onFileChange(e){ 142 let self = this; 143 let files = e.target.files || e.dataTransfer.files; 144 if (!files.length) return; 145 let file = files[0];//File对象 146 self.uploadFile = file; 147 let reader = new FileReader();//FileReader对象 148 reader.readAsDataURL(file);//该方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成(DONE),并触发 loadend 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。 149 150 reader.onload = function(e){ 151 self.imgsrc= e.target.result;//图片内容的base64编码 152 self.show = true; 153 } 154 }, 155 156 addPic: function (e) { 157 let els = this.$refs.divGenres.querySelectorAll('input[type=file]') 158 els[0].click() 159 return false 160 }, 161 162 delImage: function () { 163 this.imgsrc = ""; 164 this.show = false; 165 this.isPreview = false; 166 }, 167 168 previewImage: function (url) { 169 let vm = this; 170 vm.isPreview = true; 171 vm.previewImg = url; 172 }, 173 174 closePreview: function () { 175 let vm = this; 176 vm.isPreview = false; 177 vm.previewImg = ""; 178 }, 179 }, 180 } 181 </script> 182 183 <style> 184 .upload-button{ 185 display: block; 186 margin-top: 10px; 187 } 188 .camera-photo{ 189 text-align:center; 190 margin-top:80px; 191 } 192 .list-li { 193 194 display: flex; 195 flex-direction: column; 196 align-items: center; 197 padding: 8px; 198 margin-top:10px; 199 position: relative; 200 text-align: center; 201 margin-left: auto; 202 margin-right: auto; 203 top: 0; 204 left: 0; 205 right: 0; 206 bottom: 0; 207 } 208 .list-link img { 209 width: 150px; 210 height: 150px; 211 } 212 .list-link a:visited { 213 background-color: #465c71; 214 border: 1px #4e667d solid; 215 color: #dde4ec; 216 display: flex; 217 line-height: 1.35em; 218 padding: 4px 20px; 219 text-decoration: none; 220 white-space: nowrap; 221 overflow: hidden; 222 } 223 .list-link a:hover { 224 background-color: #bfcbd6; 225 color: #465c71;/ 226 text-decoration: none; 227 } 228 .list-link a:active { 229 background-color: #465c71; 230 color: #cfdbe6; 231 text-decoration: none; 232 } 233 .list-img-close { 234 background: #ffffff url(https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1526905315674&di=4c2d6a6985b34e141f37bc9fae7f2209&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F15%2F55%2F73%2F39I58PICCqK_1024.png) no-repeat right top; 235 border-color: #ff4a00; 236 background-position: center; 237 background-size: 35px 35px; 238 display: block; 239 float: left; 240 top: 5px; 241 width: 10px; 242 height: 10px; 243 position: absolute; 244 margin-top: 0px; 245 margin-left: 135px; 246 padding: 8px; 247 z-index: 10; 248 border-radius: 5px; 249 text-align: center; 250 } 251 .add-preview{ 252 width: 300px; 253 height: 300px; 254 } 255 .add-preview img{ 256 width: 100%; 257 height: 100%; 258 } 259 </style>

    总之,尝试之后觉得,web工程师如果要做移动端开发,还是得有安卓或者ios工程师的支持。

     补充:2018-8-24

      canvas的图片压缩原理,canvas可以改变图片大小,也可以改变图片质量。quality改变图片质量。base64只是对图片对应的二进制码,按照六位对应一个字符规则做转换,转码后是反而比原图片文件大的。但是对于小图片而言,经转换后多出来的字节传输远比多建立一个http连接开销小,所以会利用base64对小图转码来提高页面加载速度。至于图片压缩原理,简单来说,通过算法减少一张图片上的颜色差异,牺牲图片画质。比如紧挨着的颜色相近的四个像素的颜色信息压缩前大概占16个字节,压缩后变成一个颜色就能减少近4倍。quality用来控制色差的力度,值越小力度越大,颜色相差较大的两个像素也会被处理,自然被压缩后文件就越小,画质就越烂。

    用base64编码,源文件会变大,base64不能压缩图片,base64就是为了减少http请求。

  • 相关阅读:
    EBS Form菜单栏增加选项
    Oracle EBS 基础概念:弹性域-上下文字段
    EBS apps, applsys 的关系及密码更改
    设计模式-建造者模式
    微服务入门
    常见SQL编写和优化
    java 8 stream toMap问题
    mysql8.0.22在centos7.6下的简单安装
    mysql8的collate问题和修改
    springboot+security自定义登录-1-基础-自定义用户和登录界面
  • 原文地址:https://www.cnblogs.com/catherinezyr/p/9131954.html
Copyright © 2011-2022 走看看