啰嗦两句,因最近有个小项目要做一个拍照上传头像的功能,做的过程中出现了一些问题,针对这些问题做一下总结分享
问题:
1.图片转base64
2.手机拍照在ios和小米等手机下会旋转
3.图片的压缩
4.手机像素太大,进行一个等比缩放上传
啰嗦完了,上代码
<template> <div id="face"> <div class="faceBox"> <img src="" alt="" id="faceImg" ref="faceImg"> </div> <p>请拍摄清晰的全部人脸信息以方便您的进场</p> <img src="../../static/images/example.png" alt="" class="example"> <div class="startFaceBtn" v-show="!openVideo"> <button class="startFace">开始拍摄</button> <input type="file" id="upimg" accept="image/*" @change="upLoad"> </div> <button class="startFace" v-show="openVideo" @click="submit">开始上传</button> </div> </template>
上面是页面的布局
关于处理图片旋转的问题需要使用 Exif
npm install exif-js
然后在main.js中引入
import EXIF from ‘exif-js‘
Vue.prototype.Exif = EXIF
<script> import { Indicator } from ‘mint-ui‘; export default { name: ‘face‘, data() { return { openVideo: false, imgUrl: null, } }, mounted() { }, methods: { upLoad(e) { let files = e.target.files || e.dataTransfer.files; if (!files.length) return; this.picavalue = files[0]; console.log(this.picavalue.size / 1024); if (this.picavalue.size / 1024 > 10000) { this.$message({ message: "图片过大不支持上传", type: "warning" }); } else { this.imgPreview(this.picavalue); } }, imgPreview(file, callback) { let that= this; let Orientation //这里的Exif是判断图片旋转的 that.Exif.getData(file, function () { Orientation = that.Exif.getTag(file, ‘Orientation‘); }); if (!file || !window.FileReader) return; if (/^image/.test(file.type)) { let reader = new FileReader(); reader.readAsDataURL(file) reader.onloadend = function() { let result = this.result; let img = new Image(); img.src = result; img.onload = () => { let data = that.compress(img, Orientation); that.imgUrl = result; that.imgUrl = data console.log(data) that.$refs.faceImg.src = data that.openVideo = true }; }; } }, compress(img, Orientation) { let canvas = document.createElement("canvas"); let ctx = canvas.getContext("2d"); let initSize = img.src.length; let width = img.width/3.5; let height = img.height/3.5; canvas.width = width; canvas.height = height; ctx.fillStyle = "#fff"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0, width, height); console.log(Orientation) //处理ios手机旋转角度问题 if (navigator.userAgent.match(/iphone/i)) { if(Orientation != "" && Orientation != 1){ switch(Orientation){ case 6: this.rotateImg(img,‘left‘,canvas); break; case 8: this.rotateImg(img,‘right‘,canvas); break; case 3: this.rotateImg(img,‘right‘,canvas);//转两次 this.rotateImg(img,‘right‘,canvas); break; } } }else{ //处理其安卓类手机图片旋转的问题 if(Orientation != "" && Orientation != 1){ switch(Orientation){ case 6: this.rotateImg(img,‘left‘,canvas); break; case 8: this.rotateImg(img,‘right‘,canvas); break; case 3: this.rotateImg(img,‘right‘,canvas); this.rotateImg(img,‘right‘,canvas); break; } } } // ndata 为base64格式的图片上传时可直接使用,根据清晰度的要求进行调整,这里我用的是0.4 var ndata = canvas.toDataURL("image/jpeg", 0.4); return ndata; }, rotateImg (img, direction,canvas) { //最小与最大旋转方向,图片旋转4次后回到原方向 const min_step = 0; const max_step = 3; if (img == null)return; //img的高度和宽度不能在img元素隐藏后获取,否则会出错 //这里因为图片像素太大进行了一个3.5倍的缩放 let height = img.height/3.5; let width = img.width/3.5; let step = 2; if (step == null) { step = min_step; } if (direction == ‘right‘) { step ; //旋转到原位置,即超过最大值 step > max_step && (step = min_step); } else { step--; step < min_step && (step = max_step); } //旋转角度以弧度值为参数 let degree = step * 90 * Math.PI / 180; let ctx = canvas.getContext(‘2d‘); console.log(step) switch (step) { case 0: canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0, width, height); break; case 1: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, 0, -height, width, height); break; case 2: canvas.width = width; canvas.height = height; ctx.rotate(degree); ctx.drawImage(img, -width, -height, width, height); break; case 3: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, -width, 0, width, height); break; } }, submit() { //点击按钮处理上传图片的逻辑就行了,这里就不做介绍了
} } } </script>
文章参照:https://blog.csdn.net/xiaogezl/article/details/70156500