之前写过一个关于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);
},
追加:
export function pathToBase64(path) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
var canvas = document.createElement('canvas')
var c2x = canvas.getContext('2d')
var img = new Image
img.setAttribute('crossOrigin', 'anonymous');
// img.crossOrigin = "anonymous"
img.onload = function() {
canvas.width = img.width
canvas.height = img.height
c2x.drawImage(img, 0, 0)
resolve(canvas.toDataURL())
}
img.onerror = reject
img.src = path
return
}
if (typeof plus === 'object') {
var bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
bitmap.load(path, function() {
try {
var base64 = bitmap.toBase64Data()
} catch (error) {
reject(error)
}
bitmap.clear()
resolve(base64)
}, function(error) {
bitmap.clear()
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
wx.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: function(res) {
resolve('data:image/png;base64,' + res.data)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
export function base64ToPath(base64) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
base64 = base64.split(',')
var type = base64[0].match(/:(.*?);/)[1]
var str = atob(base64[1])
var n = str.length
var array = new Uint8Array(n)
while (n--) {
array[n] = str.charCodeAt(n)
}
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
}
var extName = base64.match(/data\:\S+\/(\S+);/)
if (extName) {
extName = extName[1]
} else {
reject(new Error('base64 error'))
}
var fileName = Date.now() + '.' + extName
if (typeof plus === 'object') {
var bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
bitmap.loadBase64Data(base64, function() {
var filePath = '_doc/uniapp_temp/' + fileName
bitmap.save(filePath, {}, function() {
bitmap.clear()
resolve(filePath)
}, function(error) {
bitmap.clear()
reject(error)
})
}, function(error) {
bitmap.clear()
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
var filePath = wx.env.USER_DATA_PATH + '/' + fileName
wx.getFileSystemManager().writeFile({
filePath: filePath,
data: base64.replace(/^data:\S+\/\S+;base64,/, ''),
encoding: 'base64',
success: function() {
resolve(filePath)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}