webAPP如何實現移動端拍照上傳(Vue組件示例)?

摘要:使用HTML5編寫移動Web應用,主要是爲了嘗試一下「一套代碼多處運行」,一個webapp幾乎能夠不加修改的運行在PC/Android/iOS等上面運行。可是寫到如今以爲雖然這種方式弊大於利,不只在速度上有差別,webapp對移動端的一些原生功能支持並無那麼好。我用的vue寫的系統,完成以後用webpack打包模塊,hbuilder打包成apk,可是要解決的問題並很多。如今來講說webapp拍照上傳。html

html5是支持拍照上傳或者調用本地相冊的,vue

<!--兼容安卓微信調用攝像頭-->
 <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> 實現圖片選取。html5

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

下面我就說說個人解決方法,主要是參照了網上一些實例和官網API寫出來的,請看下面的VUE組件,這個組件能夠直接引用,有興趣的同窗能夠試試:ios

  1 <template>
  2     <div>
  3         <div class="camera-photo" ref="divGenres" v-show="isPhoto" @click="choiceImg">
  4         <img style="width: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工程師的支持。web

 補充:2018-8-24算法

  canvas的圖片壓縮原理,canvas能夠改變圖片大小,也能夠改變圖片質量。quality改變圖片質量。base64只是對圖片對應的二進制碼,按照六位對應一個字符規則作轉換,轉碼後是反而比原圖片文件大的。可是對於小圖片而言,經轉換後多出來的字節傳輸遠比多創建一個http鏈接開銷小,因此會利用base64對小圖轉碼來提升頁面加載速度。至於圖片壓縮原理,簡單來講,經過算法減小一張圖片上的顏色差別,犧牲圖片畫質。好比緊挨着的顏色相近的四個像素的顏色信息壓縮前大概佔16個字節,壓縮後變成一個顏色就能減小近4倍。quality用來控制色差的力度,值越小力度越大,顏色相差較大的兩個像素也會被處理,天然被壓縮後文件就越小,畫質就越爛。canvas

用base64編碼,源文件會變大,base64不能壓縮圖片,base64就是爲了減小http請求。瀏覽器

相關文章
相關標籤/搜索