本文最后更新于:2023年3月30日 下午
1. 🎬 前情提要
😭 某天在本地开发vue
项目时,使用了vue的某个上传图片组件vue-core-image-upload
, 偶然发现ios
设备拍照上传时,图片莫名其妙被逆时针旋转了90°
😂 what?
什么鬼?ios
出现了这个鬼畜的玩意?貌似好多小伙伴都遇到了这个问题!!!有点东西啊~~
2. 🐒 go go go 也必须得解决不是
🤔 嗯?那么怎么解决呢?高能量来了
1️⃣ 既然只有ios
会出现这个毛病?你那么将是否是ios
作为参数传给后端,后端旋转回图片即可
😁 想得有点多,至于为什么就不说了吧,这个锅还得不想背而背
2️⃣ 既然让后端处理不可能,那就自己来吧(没有js搞不了的),既然是旋转出错了,那是不是只要旋转了我就把它旋转回来了,美不美?
🙈 想得美~~
3️⃣ 怎样找到是否旋转了? —> 神器:exif-js
import { EXIF } from 'exif-js';
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
imagechanged(file) { let _this = this; EXIF.getData(file, function() { EXIF.getAllTags(this); let orientation = EXIF.getTag(this, 'Orientation'); console.log('旋转数值:' + orientation); let newImage; let canvas = document.createElement('canvas'); let reader = new FileReader(); reader.readAsDataURL(file); reader.onloadend = function() { let img = new Image(); img.src = this.result; img.onload = function() { switch (orientation) { case 6: newImage = _this.rotateImg(img, 'left', canvas); break; case 8: newImage = _this.rotateImg(img, 'right', canvas); break; case 3: newImage = _this.rotateImg(img, 'right', canvas); newImage = _this.rotateImg(img, 'right', canvas); break; default: newImage = _this.rotateImg(img, 'none', canvas); break; } _this.uploadFile(newFile); return; } }; }); }
|
4️⃣ 可以看到 _this.uploadFile(newFile);
这个表示最后this.rotateImg
后再自己做上传,为什么都旋转呢?正常的可以不用旋转啊?因为Nginx
有大小限制必须压缩,为了一个小功能我偷懒了将旋转和压缩放在一起了,实际上不建议这样做,最好是各自做各自的事情(就一个上传头像的小功能算了,不折腾了)
5️⃣ this.rotateImg
什么逻辑?这就是重点了,毫无疑问在以前肯定会找一个flash
插件将之旋转?so
?选flash
插件?我才不要入坑,瞬间想到canvas
,一查资料果然可以~😁😁😁 完美
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
|
rotateImg(img, direction, canvas) { const minStep = 0; const maxStep = 3; if (img == null) return; let height = img.height; let width = img.width; let step = 2; if (step === null) { step = minStep; } if (direction === 'right') { step++; step > maxStep && (step = minStep); } else if (direction === 'none') { step = 0; } else { step--; step < minStep && (step = maxStep); } let degree = step * 90 * Math.PI / 180; let ctx = canvas.getContext('2d'); let newImage = new Image(); let imageData; switch (step) { case 0: canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0); break; case 1: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, 0, -height); break; case 2: canvas.width = width; canvas.height = height; ctx.rotate(degree); ctx.drawImage(img, -width, -height); break; case 3: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, -width, 0); break; } imageData = canvas.toDataURL('Image/jpeg', 0.1); newImage.src = imageData; return newImage; }
|
🦁 哟哟哟~~ 浪起来~~~ 完美! 点击上传,啪!报错了?叫你高兴得太早,嘚瑟吧?什么原因? this.rotateImg
返回的是一个<img src="xxx">
难道post formdata
不应该是一个file
对象so
是不是应该将之转换成file
对象?怎么转?查资料了是可以的?但是怎么将<img src="xxx">
转成file
对象?首先想到的是base64
,有其他方法,但是我首先想到的是他,不能浪费时间了就是他!因为new FileReader()
出来的src
就是base64
,还想啥想?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
dataURLtoFile(dataUrl, fileName) { let arr = dataUrl.split(','); let mime = arr[0].match(/:(.*?);/)[1]; let bstr = atob(arr[1]); let n = bstr.length; let u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], fileName, { type: mime }); }
|
🐬 到此为止真的是完美解决了哦,意不意外!惊不惊喜!刺不刺激!
🌾 温馨提示:遇到问题不要怕,一步一步分析,不要想着一下解决,一步一步来会快很多,一个问题一个问题解决最后就真的解决了!!!