之前寫過一個關於vue的上傳圖的旋轉處理。可以直接點擊查看:使用vue進行移動端上傳圖
場景:uniapp開發的h5項目,需要內嵌在app中運行,在項目首頁有一塊是自定義上傳日曆背景圖,並且需要進行裁剪。
最開始直接使用的插件市場的插件,但是由於webview的原因,該項目內嵌app後在ios上出現了無法解決的bug。故棄用了插件,並且由於需求調整目前只進行圖片的上傳旋轉處理。(下面着重旋轉的處理)
思路:
1、參考vue的處理方法,需要exif.js 獲取到圖片meta信息中的旋轉角度,故首先需要引入exif.js,(本人直接從bootcdn上搜索下載的exif.min.js )(使用import引入本地文件的方式嘗試了下沒有成功,放棄了。由於項目本身需要存在了引入第三方的js方法所以exifjs是通過動態添加js的方式全局引入的)
2、通過uni.chooseImage 獲取到圖片的臨時路徑,並且將blob臨時路徑轉化爲 file文件用於exif獲取圖片的旋轉值
3、根據獲取到旋轉值(有:1 3 6 8),如下:
//如果方向角不爲1,都需要進行旋轉
switch (Orientation) {
case 6: //需要順時針(向右)90度旋轉
console.log('(向右)90度旋轉');
break;
case 8: //需要逆時針(向左)90度旋轉
console.log('向左)90度旋轉');
break;
case 3: //需要180度旋轉 轉兩次
console.log('需要180度旋轉');
break;
default:
break;
}
4、根據網上搜索的處理圖片旋轉方法或者從往期vue的上傳圖博客中提到的,對圖片進行旋轉處理,最終拿到base64的圖片信息然後對圖片進行上傳。(1.直接上傳base64 ;2.將base64轉化爲blob文件後再傳後臺)
具體代碼如下:
1、
choiceImg(){
var that = this;
let maxWidth = 500; //壓縮圖片最大寬度
let Orientation = 1;
uni.chooseImage({
count: 1, // 能夠選擇的圖片數量
sizeType: ['original', 'compressed'], // original: 原圖, compressed: 壓縮圖, 默認二者都有
sourceType: ['album'], // album: 從相冊選擇 camera: 相機拍照
success: res => {
let imgArr = res.tempFilePaths; // 所選擇圖片的臨時路徑數組
//BlobUrl轉blob數據
uni.showToast({
icon: "none",
title: "圖片處理中..."
})
//blob數據轉file
this.objectURLToBlob(imgArr[0], function(blob) {
let files = new window.File([blob], 'file.name', { type: 'file.type' });
console.log('獲取圖片文件', files);
EXIF.getData(files, async function() {
let or = EXIF.getTag(this, 'Orientation'); //這個Orientation 就是我們判斷需不需要旋轉的值了,有1、3、6、8
console.log(or);
Orientation = or;
var img = null;
var canvas = null;
await that.comprossImage(imgArr[0], maxWidth, function(e) {
img = e.img;
canvas = e.canvas;
});
let baseStr = '';
//如果方向角不爲1,都需要進行旋轉
switch (Orientation) {
case 6: //需要順時針(向右)90度旋轉
console.log('(向右)90度旋轉');
baseStr = that.rotateImg(img, 'right', canvas);
break;
case 8: //需要逆時針(向左)90度旋轉
console.log('向左)90度旋轉');
baseStr = rotateImg(img, 'left', canvas);
break;
case 3: //需要180度旋轉 轉兩次
console.log('需要180度旋轉');
baseStr = that.rotateImg(img, 'right', canvas, 2);
break;
default:
baseStr = that.rotateImg(img, '', canvas);
break;
}
});
});
}
});
}
2、1中使用到的將blob轉化爲file方法 和圖片的壓縮方法
objectURLToBlob(url, callback) {
var http = new XMLHttpRequest();
http.open('GET', url, true);
http.responseType = 'blob';
http.onload = function(e) {
if (this.status == 200 || this.status === 0) {
callback(this.response);
}
};
http.send();
},
async comprossImage(imgSrc, maxWidth, func) {
if (!imgSrc) return 0;
return new Promise((resolve, reject) => {
uni.getImageInfo({
src: imgSrc,
success(res) {
let img = new Image();
img.src = res.path;
console.log(img);
let canvas = document.createElement('canvas');
let obj = new Object();
obj.img = img;
obj.canvas = canvas;
resolve(func(obj));
}
});
});
},
3、圖片的旋轉處理
rotateImg(img, direction, canvas, times = 1) {
console.log('開始旋轉');
//最小與最大旋轉方向,圖片旋轉4次後回到原方向
var min_step = 0;
var max_step = 3;
if (img == null) return;
//img的高度和寬度不能在img元素隱藏後獲取,否則會出錯
var height = img.height;
var width = img.width;
let maxWidth = 500;
let canvasWidth = width; //圖片原始長寬
let canvasHeight = height;
let base = canvasWidth / canvasHeight;
console.log(maxWidth);
if (canvasWidth > maxWidth) {
canvasWidth = maxWidth;
canvasHeight = Math.floor(canvasWidth / base);
}
width = canvasWidth;
height = canvasHeight;
var step = 0;
if (step == null) {
step = min_step;
}
if (direction == 'right') {
step += times;
//旋轉到原位置,即超過最大值
step > max_step && (step = min_step);
} else if (direction == 'left') {
step -= times;
step < min_step && (step = max_step);
} else {
//不旋轉
step = 0;
}
//旋轉角度以弧度值爲參數
var degree = (step * 90 * Math.PI) / 180;
var ctx = canvas.getContext('2d');
// console.log(degree)
// console.log(step)
switch (step) {
case 1:
console.log('右旋轉 90度');
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height, width, height);
break;
case 2:
//console.log('旋轉 180度')
canvas.width = width;
canvas.height = height;
ctx.rotate(degree);
ctx.drawImage(img, -width, -height, width, height);
break;
case 3:
console.log('左旋轉 90度');
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, -width, 0, width, height);
break;
default:
//不旋轉
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
break;
}
let baseStr = canvas.toDataURL('image/jpeg', 1);
// console.log(baseStr)
// return baseStr;
// replace("data:image/jpeg;base64,", "")
// 將base64轉化爲blob文件進行圖片上傳,(考慮到轉化後再上傳耗費時間暫時沒有使用,如果需要base64ToPath 方法可百度或者私信我)
// base64ToPath(baseStr).then(tempPath => {
// this.uploadBgImg(tempPath)
// });
// 自定義上傳請求
this.uploadBaseImg(baseStr);
},