( ′? ??`)现在的公司啊都流行混合开发,我们公司也不例外,非要把交互非常多的社区模块用内嵌web页展示,好吧好吧,毕竟有的应用也是这么做的,那既然是社区就肯定少不了用户上传图片的操作,在开发阶段没有发现任何问题,也是很奇怪,等到了测试阶段,发现部分机型和IOS机型拍照之后,web页获取路径之后展示的图片和图片文件全不是正确的方向,旋转了90°、180°的都有,于是去网上查找原因,结果就是……
大于2M的图片!并且是竖拍的图片!在生成照片的时候图片的Orientation属性会被重写!!!!所以部分机型和IOS 都会出现旋转的问题!
可恶!
当然方法也百度到了,只不过大部分都是只放了代码,并没有讲解,其实理解了也非常简单。
一、安装插件 ︶︿︶
解决这个问题首先是要借助插件的,因为我们前端旋转了图片只是在页面上看上去旋转了,并没有解决根本问题,于是就要用到 exif.js这个工具。
https://www.npmjs.com/package/exif-js
一个强大的读取图片数据的工具,安装也很简单文档里也有,就不多说了,因为我使用的是Vue,所以之间npm安装后在需要使用的页面引入:
import exif from "exif-js";
到这里就算完成了插件的全部安装;
二、开工!(^-^)V
首先在选择框的change事件中我们直接调用exif的方法;
let Orientation = 0; exif.getData(e.target.files[0], function() { exif.getAllTags(this); Orientation = exif.getTag(this, ‘Orientation‘); }); //e.target.files[0]为获取的第一个图片文件,如果是多个图片文件可进行遍历
这时候我们就已经获取到图片的Orientation属性了,这个属性就是图片的方向属性,不同的值代表不同的方向:
图片正常 | 1 |
图片朝右 | 6 |
图片朝左 | 8 |
图片倒置 | 3 |
后来经过测试Orientation还会有一个值,就是0,当Orientation等于0的时候图片是正常的,但0代表的意思,还没有找到。
那么现在就可以对图片进行处理了let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d"); let width = img.width; let height = img.height; switch(orientation) { case 0: //不做任何处理直接画图 canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0) break; case 1: //不做任何处理直接画图 canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0) break; case 6: //图片顺时针旋转90° canvas.height = width; canvas.width = height; ctx.rotate(Math.PI / 2); ctx.translate(0, -height); ctx.drawImage(img, 0, 0) break; case 3: //图片旋转180° canvas.height = height; canvas.width = width; ctx.rotate(Math.PI); ctx.translate(-width, -height); ctx.drawImage(img, 0, 0) break; case 8: //图片逆时针旋转90° canvas.height = width; canvas.width = height; ctx.rotate(-Math.PI / 2); ctx.translate(-height, 0); ctx.drawImage(img, 0, 0) break; case undefined: //不作任何处理直接画图 canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0) break; }
let ndata=canvas.toDataURL("image/jpeg", 1);
这里图片的处理就是把图片原原本本的在canvas上画一遍,然后把它转成正确的方向就可以了,那么缩略图就可以直接展示ndata就可以了。
但是这里还只是一张图片,我们不可能给后台传图片base64码过去,必须是图片文件才可以,那么这里就要用到base64的转码。
首先是base64转码函数的封装:
// base64转成bolb对象 dataURItoBlob(base64Data) { let byteString; if(base64Data.split(",")[0].indexOf("base64") >= 0) byteString = atob(base64Data.split(",")[1]); else byteString = unescape(base64Data.split(",")[1]); let mimeString = base64Data .split(",")[0] .split(":")[1] .split(";")[0]; let ia = new Uint8Array(byteString.length); for(let i = 0; i < byteString.length; i++) { ia[i] = byteString.charCodeAt(i); } return new Blob([ia], { type: mimeString }); },
然后将上面我们转换好的ndata通过base64转换成图片文件就可以了。
//调用转换函数将base64码转换成图片文件 let blob = this.dataURItoBlob(ndata); //将新文件名与原图片文件保持一致 blob.name = e.target.files[0].name; //将新文件放到我们需要传给后台的文件数组里 this.files.push(blob);
三、结束o(?Д?)っ
以上就是对图片旋转做的处理,很简单,我们就可以理解为图片的重绘。当然上面的方法只是单个图片的转换,如果用户同时上传了多个图片,那么就在对应的地方添加遍历循环就可以了。
如果有不足的地方希望大家补充,有不对的地方也请大家批评指正。
如果还不太明白也可以通过我的联系方式进行讨论。