前言
时光匆匆,转眼清明已过。但是杭州还是有一丝丝寒冷,风力没有春天的味道。年前积压的一些需求已经全部完成上线,这星期学了点东西,同通过文章的形式记录一下,防止以后自己忘记。
正文开始
事情是这样的,产品经理来问我,为什么图片上传之后,变成横向的了。如下图所示:
根据情景分析,这张图片是由手机拍摄的,并且上传到网站上的时候,默认就是逆时针旋转了 90 度。现在需要解决的问题是将其顺时针旋转 90 度,变成正常显示。
主角登场
本篇文章的主角便是——EXIF。简单的说,它是读取图片元数据的一个工具包,Exif.js 提供了 JavaScript 读取图像的原始数据的功能扩展,例如:拍照方向、相机设备型号、拍摄时间、ISO 感光度、GPS 地理位置等数据。
使用方法
1、通过 npm 安装。 2、通过静态资源 CDN 的形式,标签引入。
下面介绍的例子就是通过标签引入的方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet/less" type="text/css" href="./styles.less" />
<title>EXIF</title>
</head>
<body>
<div class="box">
<img width="200px" id="img" src="" alt="图片" />
<input id="input" type="file" onchange="upLoad()" />
</div>
<script>
function upLoad() {
var fileInput = document.getElementById('input')
var file = fileInput.files[0] // 获取上传图片的信息
console.log('file', file)
EXIF.getData(file, function() {
let exifTags = EXIF.getAllTags(this); // 获取上传图片的元数据
console.log('exifTags', exifTags)
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = e => {
let imgData = e.target.result;
// 8 表示 顺时针转了90; 3 表示 转了 180; 6 表示 逆时针转了90
if (
exifTags.Orientation == 8 ||
exifTags.Orientation == 3 ||
exifTags.Orientation == 6
) {
const img = new Image();
img.src = imgData;
img.onload = function () {
let cvs = document.createElement('canvas');
let ctx = cvs.getContext('2d');
//如果旋转90
if (
exifTags.Orientation == 8 ||
exifTags.Orientation == 6
) {
cvs.width = img.height;
cvs.height = img.width;
} else {
cvs.width = img.width;
cvs.height = img.height;
}
if (exifTags.Orientation == 6) {
//原图逆时针转了90, 所以要顺时针旋转90
ctx.rotate(Math.PI / 180 * 90);
ctx.drawImage(
img,
0,
0,
img.width,
img.height,
0,
-img.height,
img.width,
img.height
);
}
if (exifTags.Orientation == 3) {
//原图逆时针转了180, 所以顺时针旋转180
ctx.rotate(Math.PI / 180 * 180);
ctx.drawImage(
img,
0,
0,
img.width,
img.height,
-img.width,
-img.height,
img.width,
img.height
);
}
if (exifTags.Orientation == 8) {
//原图顺时针旋转了90, 所以要你时针旋转90
ctx.rotate(Math.PI / 180 * -90);
ctx.drawImage(
img,
0,
0,
img.width,
img.height,
-img.width,
0,
img.width,
img.height
);
}
const url = cvs.toDataURL('image/png')
let imgNode = document.getElementById('img')
imgNode.setAttribute('src', url)
}
} else {
let imgNode = document.getElementById('img')
imgNode.setAttribute('src', imgData)
}
}
})
}
</script>
<script src="https://cdn.bootcss.com/exif-js/2.3.0/exif.min.js"></script>
</body>
</html>
上述代码获取到图片的数据之后,关键是 Orientation
参数,它表示拍摄方向。通过返回的数字判断这张图片旋转的方向,然后通过 canvas 画布再重新绘制一张图片,最后输出到 DOM 节点。
总结
exif 还有很多值得研究的地方,本篇文章只是需要针对旋转方向去做重绘,顾之研究了片面,需要对图像做深度研究的同学,可以深究。