有時候我們要手機上傳圖片到網上提交數據,但是可能圖片的文件比較大,像拍照拍出來的就有可能有2m。這個時候就需要把圖片壓縮一下,如果在微信中的話可以調用微信的接口上傳文件,但是有個更加通用的辦法,就是用canvas來壓縮上傳。
用canvas壓縮圖片的原理就是讀取圖片的文件,然后把圖片畫在畫布上,再用canvas自帶的一個接口:
canvas.toDataURL(type,encoderOptions);
這里的第一個參數type就是圖片的格式,默認會讀取image/png。
第二個參數就比較重要了,這個參數就決定了圖片壓縮的程度,可以在0-1中選擇一個值,當然推薦不要低于0.5,因為這樣保存后的圖片質量不太好。
這個方法執行完后會返回一個值,就是圖片的base64格式的字符串,這個字符串就可以上傳到服務端。
前段時間我在用這個方法上傳圖片的時候發現在ios下的圖片上傳會有一個bug,就是canvas轉換后的圖片會逆時針旋轉90°,這樣的話就不是我想要的效果了。所以在網上搜集了很多解決的方案,發現可以用一個插件EXIF.js來解決這個功能。
先來講講這個插件是用來做什么的,這個插件會讀取圖片的信息,然后返回一個值,這個值就是圖片的旋轉位置,6代表圖片需要順時針(向左)90度旋轉才是正常的,8代表需要逆時針(向右)90度旋轉,3表示圖片是上下顛倒的。
下面是具體的代碼:
function compress(img, fileType) {
var canvas = document.createElement("canvas");
var rotateshow;
EXIF.getData(img, function(){
EXIF.getAllTags(img);
Orientation = EXIF.getTag(img,'Orientation');
switch (Orientation){
case 6:
rotateshow = rotateImg(img,'left',canvas,fileType);
break;
case 8:
rotateshow = rotateImg(img,'right',canvas,fileType);
break;
case 3:
rotateImg(img,'right',canvas,fileType);
rotateshow = rotateImg(img,'right',canvas,fileType);
break;
default:
rotateshow = img.src;
}
toPreviewer(rotateshow);
});
}
不過之前我在的EXIF.js里發現一個問題就是getData獲取不到img的屬性,然后在我在這個插件里找到了相關的代碼發現有一段代碼判斷圖片的時候判斷不對,導致代碼不能執行下去:
EXIF.getData = function(img, callback) {
/*if ((self.Image && img instanceof self.Image)
|| (self.HTMLImageElement && img instanceof self.HTMLImageElement)
&& !img.complete)
return false;*/
if (!imageHasData(img)) {
getImageData(img, callback);
} else {
if (callback) {
callback.call(img);
}
}
return true;
};
所以就把這里注釋掉了,在判斷完圖片的朝向后就要對圖片進行處理,圖片的旋轉可以把圖片畫在canvas里然后用canvas的rotate方法進行旋轉然后調用toDataURL來進行壓縮,具體的代碼如下:
var min_step = 0;
var max_step = 3;
//var img = document.getElementById(pid);
if (img == null)return;
//img的高度和寬度不能在img元素隱藏后獲取,否則會出錯
var height = img.height;
var width = img.width;
//var step = img.getAttribute('step');
var step = 2;
if (step == null) {
step = min_step;
}
if (direction == 'right') {
step++;
//旋轉到原位置,即超過最大值
step > max_step && (step = min_step);
} else {
step--;
step < min_step && (step = max_step);
}
var degree = step * 90 * Math.PI / 180;
var ctx = canvas.getContext('2d');
switch (step) {
case 0:
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0);
break;
case 1:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height);
break;
case 2:
canvas.width = width;
canvas.height = height;
ctx.rotate(degree);
ctx.drawImage(img, -width, -height);
break;
case 3:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, -width, 0);
break;
}
return canvas.toDataURL(fileType,0.75);
}
至此圖片上傳bug就解決了,可以到我的github上查看我的源碼:
https://github.com/Tinsson/Blog_demo/blob/master/picUpload/sign.html