前些天公司要求在微信移動端做上傳圖片並預覽的功能,要求能夠調用攝像頭拍照並立即預覽。 在網上搜了一些方法,開始自己寫了個簡單的功能實現代碼。結果發現移動端拍照出來的圖片動不動就2M+,又因為要批量上傳,為用戶的流量和上傳速度考慮,我決定做一下優化,看能不能在預覽前就壓縮一下圖片尺寸。 結果又是一陣百 ...
前些天公司要求在微信移動端做上傳圖片並預覽的功能,要求能夠調用攝像頭拍照並立即預覽。
在網上搜了一些方法,開始自己寫了個簡單的功能實現代碼。結果發現移動端拍照出來的圖片動不動就2M+,又因為要批量上傳,為用戶的流量和上傳速度考慮,我決定做一下優化,看能不能在預覽前就壓縮一下圖片尺寸。
結果又是一陣百度,發現一個靠譜的封裝好的base64圖片預覽及壓縮的方法。
直接上下載地址吧:
http://www.imwinlion.com/wp-content/uploads/2016/05/localresizeimg.rar
源碼和用法都很簡單,稍微看下源碼就懂了,為了相容移動端,請一定將/path/mobileBUGFix.mini.js加入到頁面中。反正我是加了的,沒加會有什麼後果,大家有空可以測一下。
這個插件還是比較好用的,問題是我要批量上傳,怎麼搞?這個插件只能單個圖片上傳!
所以我後來改良了一下插件,在插件內部指向文件時,做了一個迴圈,話不多說,代碼也很簡單,直接上代碼
1 /** 2 * 獲得base64 3 * @param {Object} obj 4 * @param {Number} [obj.width] 圖片需要壓縮的寬度,高度會跟隨調整 5 * @param {Number} [obj.quality=0.8] 壓縮質量,不壓縮為1 6 * @param {Function} [obj.before(this, blob, file)] 處理前函數,this指向的是input:file 7 * @param {Function} obj.success(obj) 處理後函數 8 * @example 9 * 10 */ 11 $.fn.localResizeIMG = function(obj) { 12 this.on('change', function() { 13 //批量預覽壓縮 14 var file,blob; 15 var _this=this; 16 if(this.files.length>1){ 17 for(var i = 0, len=_this.files.length;i<len;i++){ 18 file=_this.files[i]; 19 if (window.createObjectURL!=undefined) { // basic 20 blob = window.createObjectURL(file) ; 21 } else if (window.URL!=undefined) { // mozilla(firefox) 22 blob = window.URL.createObjectURL(file) ; 23 } else if (window.webkitURL!=undefined) { // webkit or chrome 24 blob = window.webkitURL.createObjectURL(file) ; 25 } 26 if ($.isFunction(obj.before)) { 27 obj.before(_this, blob, file) 28 } 29 if(file.size/1024>300){ 30 obj.quality=300/(file.size/1024) 31 }else{ 32 obj.quality=1 33 } 34 _create(blob,obj.quality, file); 35 } 36 }else{ 37 //單張預覽壓縮圖片 38 file = this.files[0]; 39 if (window.createObjectURL!=undefined) { // basic 40 blob = window.createObjectURL(file) ; 41 } else if (window.URL!=undefined) { // mozilla(firefox) 42 blob = window.URL.createObjectURL(file) ; 43 } else if (window.webkitURL!=undefined) { // webkit or chrome 44 blob = window.webkitURL.createObjectURL(file) ; 45 } 46 // 執行前函數 47 if ($.isFunction(obj.before)) { 48 obj.before(this, blob, file) 49 }; 50 if(file.size/1024>300){ 51 obj.quality=300/(file.size/1024) 52 }else{ 53 obj.quality=1 54 } 55 _create(blob,obj.quality, file); 56 } 57 this.value = ''; // 清空臨時數據 58 }); 59 60 /** 61 * 生成base64 62 * @param blob 通過file獲得的二進位 63 */ 64 function _create(blob,quality) { 65 console.log(quality); 66 var img = new Image(); 67 img.src = blob; 68 img.onload = function() { 69 var that = this; 70 //生成比例 71 var w = that.width, 72 h = that.height, 73 quality = w / h; 74 w = obj.width || w; 75 h = w / quality; 76 77 //生成canvas 78 var canvas = document.createElement('canvas'); 79 var ctx = canvas.getContext('2d'); 80 $(canvas).attr({ 81 width: w, 82 height: h 83 }); 84 ctx.drawImage(that, 0, 0, w, h); 85 86 /** 87 * 生成base64 88 * 相容修複移動設備需要引入mobileBUGFix.js 89 */ 90 var base64 = canvas.toDataURL('image/png', quality || 0.8); 91 92 // 修複IOS 93 if (navigator.userAgent.match(/iphone/i)) { 94 var mpImg = new MegaPixImage(img); 95 mpImg.render(canvas, { 96 maxWidth: w, 97 maxHeight: h, 98 quality: quality || 0.8 99 }); 100 base64 = canvas.toDataURL('image/png', quality || 0.8); 101 } 102 103 // 修複android 104 if (navigator.userAgent.match(/Android/i)) { 105 var encoder = new JPEGEncoder(); 106 base64 = encoder.encode(ctx.getImageData(0, 0, w, h), parseFloat(quality).toFixed(1) * 100 || 80); 107 } 108 109 // 生成結果 110 var result = { 111 base64: base64, 112 clearBase64: base64.substr(base64.indexOf(',') + 1) 113 }; 114 115 // 執行後函數 116 obj.success(result); 117 }; 118 } 119 }; 120 121 122 // 例子 123 /* 124 $('input:file').localResizeIMG({ 125 width: 100, 126 quality: 0.1, 127 //before: function (that, blob) {}, 128 success: function (result) { 129 var img = new Image(); 130 img.src = result.base64; 131 132 $('body').append(img); 133 console.log(result); 134 } 135 }); 136 */
改良之後,我判斷了input[type=files].files的長度,如果是批量上傳的話,長度應該是大於1的,這個邏輯應該很好理解;然後迴圈每一個files,獲取每個圖片的size(圖片大小),我這裡的圖片尺寸判斷是寫死了的300kb,如果這張圖片>300kb,就壓縮尺寸,如果相反,則按原尺寸預覽。如果你用我改良後的代碼,調用方法後的quality屬性就不用賦值了。
with屬性:你壓縮後圖片的寬度,不宜太小,我是設置的400,太小會失真。
before方法:開始壓縮前執行函數
success方法:壓縮成功後的回調函數,一般就是寫預覽代碼,如果你要非同步上傳,這裡也可以寫ajax
說了這麼多,再來說一下移動端的照相機調用,文件格式限制吧
很簡單,一行搞定
1 <input id="images-multiple" class="weui-uploader__input" type="file" accept="image/*" multiple="multiple">
accept:接收文件的類型
multiple:可多選(android手機設置此項後,不能調用相機,只能從相冊中選擇;IOS手機體驗還是很溜的)
id和calss自行制定就OK了。
目前的我頁面在微信內跑,尚未發現問題,如有疑問歡迎探討!!
提供一個GITHUB的類似解決方案:內容還沒來得及看,有興趣可以去看看
https://github.com/lyg945/localResizeIMG/tree/master/