最近在作的項目中,無論是移動端仍是後臺系統都涉及到了手機照片壓縮上傳的問題,作完功能測試的時候發現圖片回顯的時候有些順時針旋轉了90°(豎拍照片,無論是ios仍是android都存在這問題),後來百度了一下才知道是跟圖片的EXIF(可交換圖像文件格式)中的Orientation(旋轉參數)有關,那麼問題就好處理了,咱們能夠獲取上傳圖片的Orientation值,根據不一樣的值對圖片作旋轉處理。javascript
可交換圖像文件格式(Exchangeable image file format,官方簡稱Exif),是專門爲數碼相機的照片設定的,能夠記錄數碼照片的屬性信息和拍攝數據。只要是數碼相機(包括手機)拍出來的照片都帶有這個參數,旋轉的方向有四種狀況。exif.js能夠幫助咱們獲取Orientation值(exif.js讀取圖像的元數據),後來我以import EXIF from './exif.js'方式引入發現文件中的EXIF方法並無對外暴露出來,所以稍稍改寫了一下。這是新的exif.js(大家能夠引用這個exif.js)
引用exif.js後,獲取Orientation的核心代碼,記得先var Orientation聲明Orientationjava
EXIF.getData(img, function () {//獲取照片Orientation,主要是修復豎拍照片順時針旋轉90°的問題(Orientation:6) EXIF.getAllTags(this); Orientation = EXIF.getTag(this, 'Orientation'); });
ctx.rotate(angle);
方法介紹參照canvas rotate() android
旋轉的中心點默認是canvas 的起點,即圓點位置(0, 0)。旋轉的原理以下圖:ios
旋轉以後,若是從圓點(0, 0)進行 drawImage(),那麼畫出來的位置就是在左圖中的旋轉90°後的位置,不在可視區域。旋轉以後,座標軸也跟着旋轉了,想要顯示在可視區域呢,須要將 ( 0, 0 ) 點往 y 軸的反方向移 y 個單位,此時的起始點則爲 ( x, -y )(這種狀況就是咱們使用手機豎拍圖片上傳後順時針旋轉90°的狀況)。canvas
同理,能夠得到旋轉 -90°後的起始點爲 ( -x, y ),旋轉 180 度後的起始點爲 ( -x, -y )。
核心代碼以下測試
var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); // 設置 canvas 的寬度和高度 // canvas.width = w; // canvas.height = h; // ctx.drawImage(img, 0, 0, w, h); if (Orientation == 3) { canvas.width = w; canvas.height = h; ctx.rotate(Math.PI); ctx.drawImage(img, 0, 0, -w, -h); } else if (Orientation == 8) { canvas.width = h; canvas.height = w; ctx.rotate(Math.PI * 3 / 2); ctx.drawImage(img, 0, 0, -w, h); } else if (Orientation == 6) { canvas.width = h; canvas.height = w; ctx.rotate(Math.PI / 2); ctx.drawImage(img, 0, 0, w, -h); } else { canvas.width = w; canvas.height = h; ctx.drawImage(img, 0, 0, w, h); }
隨着手機拍照像素愈來愈高,照片大小愈來愈大。圖片上傳的壓縮通常是:第一是對上傳的圖片寬高作大小限制。this
// 不要超出最大寬度 var w = Math.min(_this.maxWidth, img.width); // 高度按比例計算 var h = img.height * (w / img.width);
第二是經過canvas.toDataURL(type, encoderOptions)方法設置壓縮比,方法參考canvas.toDataUrl()spa
核心代碼以下:code
setQuality: function (file) { //alert(file.size+','+this.maxSize); if (file.size < 1024 * 1024) {//0-1mb this.quality = 0.4; } if (file.size < 1024 * 1024 && file.size > 1024 * 1024 * 2) {//1-2mb this.quality = 0.3; } if (file.size < 1024 * 1024 * 3 && file.size > 1024 * 1024 * 2) {//2-3mb this.quality = 0.2; } if (file.size < 1024 * 1024 * 4 && file.size > 1024 * 1024 * 3) {//3-4mb this.quality = 0.15; } if (file.size < 1024 * 1024 * 5 && file.size > 1024 * 1024 * 4) {//4-5mb this.quality = 0.12; } if (file.size < 1024 * 1024 * 6 && file.size > 1024 * 1024 * 5) {//5-6mb this.quality = 0.11; } if (file.size < 1024 * 1024 * 7 && file.size > 1024 * 1024 * 6) {//6-7mb this.quality = 0.1; } if (file.size < 1024 * 1024 * 8 && file.size > 1024 * 1024 * 7) {//7-8mb this.quality = 0.08; } if (file.size < 1024 * 1024 * 10 && file.size > 1024 * 1024 * 8) {//8-10mb this.quality = 0.06; } }
var base64 = canvas.toDataURL('image/jpeg', _this.quality); setTimeout(function () { _this.imgData[id].uploadFiles.push(base64); _this.imgData[id].filesLength = _this.imgData[id].uploadFiles.length; }, 100);
拍照上傳功能可拆分爲圖片壓縮以及對獲取到數碼圖片Orientation值進行相應的處理。這是小白第一次寫技術貼,可能我寫得並非我想表達的,寫得很差的地方請各位大神指點,有疑問的能夠留言交流。orm