项目背景:微信公众号,不想用微信JS-SDK 图片上传功能
发现部分机型,微信内置浏览器,vant-upload组件选取图片会发生旋转
vue.js + vantUI + exif.js
解决方案:利用H5的canvas标签操作图片旋转
代码注释不全,逻辑: 选择图片 =》读取文件后 =》 判断图片方向 =》用画布重画图片并旋转 =》保存图片文件
此文章同时发表在APICloud论坛
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>图片处理canvas旋转方向</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.9/lib/index.css" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vant@2.9/lib/vant.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/exif-js/2.3.0/exif.js"></script>
<style type="text/css">
</style>
</head>
<body>
<div id="app">
<van-field required :border="false" name="uploader" label="照片">
<template #input>
<van-uploader v-model="fileList" :max-count="1" :after-read="afterRead"></van-uploader>
</template>
</van-field>
</div>
</body>
<script type="text/javascript">
new Vue({
el: '#app',
data() {
return {
fileList: []
}
},
methods: {
async afterRead(file) {
var _this = this; // vue对象
// file.status = 'uploading';
// file.message = '图片处理';
EXIF.getData(file.file, function() {
// 旋转方向 1:0° 3:180° 6:顺时针90° 8:逆时针90°
var Orientation = EXIF.getTag(this, "Orientation");
var imgName = this.name; // 原图片名称
var imgType = this.type; // 原图片类型
if (!this || !window.FileReader) return; // 看支持不支持FileReader
// 创建一个reader
var reader = new FileReader();
// 将图片2将转成 base64 格式
reader.readAsDataURL(this);
reader.onloadend = function() {
var img = new Image();
img.src = reader.result;
var width = img.width;
var height = img.height;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
switch (Number(Orientation)) {
case 3:
canvas.width = width;
canvas.height = height;
ctx.rotate(Math.PI / 180 * 180);
ctx.drawImage(img, 0, 0, img.width, img.height, -img.width, -img.height, img.width, img.height);
break;
case 6:
canvas.width = height;
canvas.height = width;
ctx.rotate(Math.PI / 180 * 90);
ctx.drawImage(img, 0, 0, img.width, img.height, 0, -img.height, img.width, img.height);
break;
case 8:
canvas.width = height;
canvas.height = width;
ctx.rotate(Math.PI / 180 * -90);
ctx.drawImage(img, 0, 0, img.width, img.height, -img.width, 0, img.width, img.height);
break;
default:
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0);
break;
}
var fileBase64 = canvas.toDataURL(imgType);
var newFile = _this.dataURLtoFile(imgName, imgType, fileBase64)
file.content = fileBase64
file.file = newFile
file.status = 'done'
}
});
},
dataURLtoFile(imgName, imgType, dataurl) {
var arr = dataurl.split(","),
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], imgName, {
type: imgType
});
},
}
})
</script>
</html>