安装方式:
npm install exif-js --save
或游览器本地引入:
<script src="exif.js"></script>
读取图像的元数据:
在最近的活动中,遇到了用户上传图片时图片方向偏转的问题。针对这个问题,通过google得到exif.js可以获取照片的元数据,例如:拍照方向、相机设备型号、拍摄时间、ISO 感光度、GPS 地理位置等数据。EXIF 数据主要来自拍摄的照片,多用于移动端开发,PC 端也会用到,兼容性良好,兼容主流浏览器,IE10 以下不支持。
使用方法:
EXIF.getData(document.getElementById('imgElement'), function(){
EXIF.getAllTags(this);
EXIF.getTag(this, 'Orientation');
});
API:
名称 说明
EXIF.getData(img, callback) 获取图像的数据
EXIF.getTag(img, tag) 获取图像的某个数据
EXIF.getAllTags(img) 获取图像的全部数据,值以对象的方式返回
EXIF.pretty(img) 获取图像的全部数据,值以字符串的方式返回
HTML代码:
<div @touchend="toAvatar()">
<div id="imgPlaceholder" v-if="!show"></div>
<img id="avatar" v-else :src="userInfo.headerStatus ? userInfo.avatar : defaultImg" :style="{borderRadius:'50%',width:'0.93rem',height:'0.93rem'}">
<input type="file" @change="imageFileChange($event)" ref="file" accept="image/*" multiple style="display:none">
</div>
<div class="test">
<img :src="compressFrondImage" style="width:100%"> <!--压缩之前的图片-->
<img :src="compressEndImage" width="200"> <!--压缩之后的图片-->
</div>
JavaScript代码:
<script>
import EXIF from 'exif-js';
import { _updateAvatar } from "../axios/index.js";
import Mint from 'mint-ui';
export default {
name:'',
data() {
return {
show:false,
compressFrondImage:'',// 压缩之前的图片
compressEndImage:'', // 压缩之后的图片
defaultImg:'img/my/default.png',
userInfo: {
avatar:'',
headerStatus:null
}
}
},
methods:{
toAvatar() {
this.$refs.file.click();
},
/**
* 图片文件发生变化
*/
imageFileChange (e) {
this.file = e.target.files[0];
if (!this.file) return;
let fileSize = (this.file.size/1024/1024).toFixed(4);
console.log('oldSize: '+fileSize+' M');
if (this.file) {
// FileReader
let reader = new FileReader()
reader.readAsDataURL(this.file)
reader.onload = (e) => {
// console.log(e.target)
this.compressFrondImage = e.target.result
this.compressImages(this.compressFrondImage)
}
},
/**
* 压缩图片
*/
compressImages (res) {
let defaultImage = {
width: 210,
height: 210,
quality: 0.8, // 压缩图片的质量
orientation: '' // 获取照片方向角属性,用户旋转控制
}
var img = new Image()
img.src = res
let initSize = img.src.length
img.onload = () => {
console.log('压缩之前宽度: ' + img.width)
console.log('压缩之前高度: ' + img.height)
var canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d')
if (img.width > defaultImage.width) {
img.height = img.height * (defaultImage.width / img.width)
img.width = defaultImage.width
}
if (img.height > defaultImage.height) {
img.width *= defaultImage.height / img.height
img.height = defaultImage.height
}
canvas.width = img.width
canvas.height = img.height
ctx.clearRect(0, 0, canvas.width, canvas.height)
EXIF.getData(this.file, () => { // IMG_FILE为图像数据
// 是否是iPhone手机,iPhone 拍照之后的压缩是逆时针旋转90,针对iphone做一下处理
if (navigator.userAgent.match(/iphone/i)) {
defaultImage.orientation = EXIF.getTag(this.file, 'Orientation')
// translate是平移变换,scale(-1,1)是向左翻转,rotate是顺时针旋转。
// defaultImage.orientation = 6 // 测试iPhone手机
// alert('Orientation:' + defaultImage.orientation) // 拍照方向
switch (Number(defaultImage.orientation)) {
case 2:
ctx.translate(img.width, 0)
ctx.scale(-1, 1)
ctx.drawImage(img, 0, 0, img.width, img.height)
break
case 3:
ctx.rotate(180 * Math.PI / 180)
ctx.drawImage(img, -img.width, -img.height, img.width, img.height)
break
case 4:
ctx.translate(img.width, 0)
ctx.scale(-1, 1)
ctx.rotate(180 * Math.PI / 180)
ctx.drawImage(img, -img.width, -img.height, img.width, img.height)
break
case 5:
ctx.translate(img.width, 0)
ctx.scale(-1, 1)
ctx.rotate(90 * Math.PI / 180)
ctx.drawImage(img, 0, -img.width, img.height, img.width)
break
case 6:
canvas.width = img.height
canvas.height = img.width
ctx.rotate(90 * Math.PI / 180)
ctx.drawImage(img, 0, 0, img.width, -img.height)
break
case 7:
ctx.translate(img.width, 0)
ctx.scale(-1, 1)
ctx.rotate(270 * Math.PI / 180)
ctx.drawImage(img, -img.height, 0, img.height, img.width)
break
case 8:
ctx.rotate(270 * Math.PI / 180)
ctx.drawImage(img, -img.height, 0, img.height, img.width)
break
default:
ctx.drawImage(img, 0, 0, img.width, img.height)
}
} else {
ctx.drawImage(img, 0, 0, img.width, img.height)
}
var imgUrl = canvas.toDataURL('image/jpeg', defaultImage.quality)
// 压缩之后的base64 图片地址
this.compressEndImage = imgUrl
// TODO 上传图片文件
this.uploadImage()
})
}
},
/**
* 上传图片
*/
uploadImage: function () {
//创建FormData对象
let data = new FormData();
let newFile = this.base64ToFileObject(this.compressEndImage);
console.log('newSize: '+(newFile.size/1024/1024).toFixed(4)+' M');
//为FormData对象添加数据
data.append('head', newFile);
// this.fileData = data;
this.submit(data);
},
async submit(fileData) {
let _self = this;
const res = await _updateAvatar(fileData,{user:'loading'});
if (res.status === 200) {
// console.log(res);
if (res.data.code === 1) {
_self.getUserInfo();
Mint.Toast({
message: '修改成功',
position: 'center',
duration: 1200
});
}
}
},
base64ToFileObject(base64) {
base64=base64.split(',')[1];
base64=window.atob(base64);
var ia = new Uint8Array(base64.length);
for (var i = 0; i < base64.length; i++) {
ia[i] = base64.charCodeAt(i);
};
var blob=new Blob([ia], {type:"image/jpeg"});
var newFile = new File([blob],"abc.jpeg");
return newFile;
},
},
}
}
</script>