鱼塘码农

菜鸟学习记录
鱼海无涯

webapp图片上传后自动旋转90度问题处理及图片压缩js

最近在做一个webapp项目的时候,使用了vant的图片上传插件,在测试的时候发现我的红米手机上传图片时,手机竖拍的照片上传后自动逆时针旋转了90度,而横拍的不会。因为上传后台后有一个图片识别功能,旋转了的图片识别不出来,所以开始搜索怎么把图片转回来,在这一过程中遇到了很多问题,记录一下。

旋转图片是根据图片中保存的拍摄信息里面的Orientation来判断的,Orientation有四个值,1代表正常,6代表被逆时针旋转了90度,8是顺时针旋转了90度,3代表被旋转了180度。也不知道为啥手机竖着拍的时候这个值会是6(找了好多部手机测试,竖拍的时候都是6)。而多找了几部手机进一步测试的时候发现,大多数手机即使Orientation值是6,上传以后也是正常直立的照片,没有被旋转,而连续找了三部红米手机,手机竖拍的照片都被逆时针旋转了90度。到此这个问题就很神奇了,不知道是红米手机的问题还是红米手机跟vant的适配问题。百度里找到的都是IOS手机出现这个问题,而我这里是红米,IOS没有问题。因身边没有小米,所以不知道是不是MIUI的问题。

下面直接上代码:
第一步:安装exif,获取照片的Orientation就是用exif实现的。

npm install exif-js --save

第二步:JS文件中,我是单独写了个JS文件引用的,JS文件名字是compressFile.js
compressFile.js中先引入exif

import EXIF from "exif-js";

将方法暴露出去

export default compressFile;

第三步:main.js引用js文件

import compressFile from "./assets/compressFile";
Vue.prototype.$compressFile = compressFile;

第四步:完善compressFile.js,我这里是旋转加图片压缩都有的

/**
 * 压缩图片
 * @param file 图片文件
 * @param callback 回调函数,压缩完要做的事,例如ajax请求等。
 */
import EXIF from "exif-js";

function compressFile(file,callback){
  let Orientation;
  EXIF.getData(file, function (){
    Orientation = EXIF.getTag(this, "Orientation")//获取到Orientation值
    let name = file.name;//将图片的名称预存一下
    let fileObj = file;
    let reader = new FileReader()
    reader.readAsDataURL(fileObj) //图片转base64
    reader.onload = function(e) {
      let image = new Image() //新建一个img标签(还没嵌入DOM节点)
      image.src = e.target.result
      image.onload = function () {
        let canvas = document.createElement('canvas'), // 新建canvas
          context = canvas.getContext('2d'),//创建一个画布
          imageWidth = image.width,    //保存一下图片的宽高,如果需要改变尺寸,可在此处理
          imageHeight = image.height,
          data ='';
        canvas.width = imageWidth
        canvas.height = imageHeight
        //判断要旋转的角度
        if (Orientation != "" && Orientation != 1) {
          switch (Orientation) {
            case 6: //需要顺时针(向左)90度旋转
              console.log('顺时针90度');
              canvas.width = imageHeight;
              canvas.height = imageWidth;
              //↑↑↑图片旋转的时候是以图片的左上角为圆心,旋转过后图片原来的长变成了宽,宽变成了长,所以需要替换一下。下面是一样的道理
              context.rotate(90*Math.PI/180);
              //↑↑↑这里是旋转图片方法,旋转的度数*Math.PI/180,
              //↑↑↑为什么要乘可以看https://www.w3school.com.cn/tags/canvas_rotate.asp
              context.drawImage(image, 0, 0, imageWidth, -imageHeight)
              //↑↑↑在画布上将图片画出来。参数中imageWidth和-imageHeight我猜是因为旋转之后宽高发生交换了,但是多次测试也没搞明白这样写的逻辑
              break;
            case 8: //需要逆时针(向右)90度旋转
              console.log('逆时针90度');
              canvas.width = imageHeight;
              canvas.height = imageWidth;
              context.rotate(270*Math.PI/180);
              context.drawImage(image, 0, 0, -imageWidth, imageHeight)
              break;
            case 3: //需要180度旋转
              console.log('180度');
              context.rotate(180*Math.PI/180);
              context.drawImage(image, 0, 0, -imageWidth, -imageHeight)
              break;
            default:
              context.drawImage(image, 0, 0, imageWidth, imageHeight)
              break;
          }
        } else {
          context.drawImage(image, 0, 0, imageWidth, imageHeight)
        }
        data = canvas.toDataURL('image/jpeg',0.5)
        //压缩图片 0.5是图片质量,0.5是以前的二分之一质量,并不是完全压缩到原图的二分之一大小,
        let arr = data.split(','), mime = arr[0].match(/:(.*?);/)[1], // 转成blob
          bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        let files = new window.File([new Blob([u8arr], {type: mime})], name, {type: 'image/jpeg'}) // 转成file
        callback({content:data,file:files}) // 回调,参数是我的回调方法里要用的
      }
    }
  })
};

export default compressFile;

上面是没有判断手机型号的,因为我只在红米手机上遇到过问题,所以加了个判断手机型号,只需要在“判断要旋转的角度”那句注释下面的if之前加两行,并且把if判断改一下就行了

//判断手机型号
let UA = navigator.userAgent,
  isRedmi = /Redmi/i.test(UA);
//判断要旋转的角度
if (Orientation != "" && Orientation != 1 && isRedmi) {

页面调用的时候:

uploadBtnImg(file){//这里是组件的图片上传事件,获取到图片,
  //将图片和要回调图片的方法都传给js,js里处理好照片再调用回调方法把图片返回即可。
   this.$compressFile(file.file,this.uploadBtn);
},

至此一个旋转加压缩的JS就写完了,总体还有很多问题,待之后慢慢理解。

文章内容可能来自网络,纯为学习使用,若有侵权,请联系我删除 | 当前页面:鱼塘码农 » webapp图片上传后自动旋转90度问题处理及图片压缩js

评论