iOS和小米手机拍照上传后,在web端显示旋转

Posted on 2018-09-07 11:27  Rh九尾鱼  阅读(...)  评论(...编辑  收藏

( ′◔ ‸◔`)现在的公司啊都流行混合开发,我们公司也不例外,非要把交互非常多的社区模块用内嵌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(゚Д゚)っ

以上就是对图片旋转做的处理,很简单,我们就可以理解为图片的重绘。当然上面的方法只是单个图片的转换,如果用户同时上传了多个图片,那么就在对应的地方添加遍历循环就可以了。

如果有不足的地方希望大家补充,有不对的地方也请大家批评指正。

如果还不太明白也可以通过我的联系方式进行讨论。

 

返回顶部