云龙叔叔
云龙叔叔
  • 发布:2020-08-10 09:39
  • 更新:2022-08-24 16:32
  • 阅读:2357

图片旋转解决方案

分类:uni-app

前言:

目前测试图片旋转只会出现在ios H5版本上,咨询过同行和ios原生,图片旋转是会发生在canvas压缩或者裁剪上,原生暂未发现图片旋转。

解决思路:

H5版本使用exif-js获取Orientation 获取图片旋转方向,使用canvans进行旋转。

代码

// #ifndef APP-PLUS  
import Exif from "exif-js"  
// #endif  
//H5图片入口  
const rotatePic = async function(file,name,success) {  
    if(!isPicture(name)) return null;  
    let Orientation = 1;    
    await getImageTag(file,(e)=>{  
        if(e != undefined) Orientation = e;   
    })  

    var img = null;    
    var canvas = null;    
    await comprossImage(file, function(e) {    
        img = e.img;    
        canvas = e.canvas;    
    })    
    let baseStr = '';    

    //如果方向角不为1,都需要进行旋转    
    switch(Orientation){    
        case 6://需要顺时针(向右)90度旋转    
            console.log('(向右)90度旋转');    
            baseStr = rotateImg(img,'right',canvas);    
            break;    
        case 8://需要逆时针(向左)90度旋转    
            console.log('向左)90度旋转');    
            baseStr = rotateImg(img,'left',canvas);    
            break;    

        case 3://需要180度旋转 转两次    
            console.log('需要180度旋转');    
            baseStr = rotateImg(img,'right',canvas, 2);    
            break;    
        default:    
            baseStr = rotateImg(img,'',canvas);    
            break;    
    }    
    return baseStr  
}  

/**  
 * @desc 获取图片信息,使用exif.js库,具体用法请在github中搜索    
 * @param {Object} file 上传的图片文件     
 * @return {Promise<Any>} 读取是个异步操作,返回指定的图片信息    
 */    
const getImageTag  = function (file, suc)  {    
    if (!file) return 0;    
    return new Promise((resolve, reject) => {    
        /* eslint-disable func-names */    
        // 箭头函数会修改this,所以这里不能用箭头函数    
        let imgObj = new Image()    
        imgObj.src = file    
        console.log(imgObj)    
        let _this = this;  
        uni.hideLoading()  

        uni.getImageInfo({    
            src: file,    
            success(res) {    
                let obj = {  
                    src:res.path  
                }  
                Exif.getData(obj, function () {    

                    let or = Exif.getTag(this,'Orientation');//这个Orientation 就是我们判断需不需要旋转的值了,有1、3、6、8    

                    resolve(suc(or))    
                });    
            }    
        })    
    });    
}  

//创建图片  
const comprossImage = async (imgSrc, func) => {    
    if(!imgSrc) return 0;    
    return new Promise((resolve, reject) => {    
        uni.getImageInfo({    
            src: imgSrc,    
            success(res) {    
                let img = new Image();    
                img.src = res.path;    

                let canvas = document.createElement('canvas');    

                let obj = new Object();    
                obj.img = img;    
                obj.canvas = canvas;    
                resolve(func(obj));    
            }    
        });    
    })    
}    

//网上提供的旋转function    
const rotateImg = (img, direction, canvas, times = 1) => {     
    console.log('开始旋转')    
    //最小与最大旋转方向,图片旋转4次后回到原方向      
    var min_step = 0;      
    var max_step = 3;      
    if (img == null)return;      

    //img的高度和宽度不能在img元素隐藏后获取,否则会出错      
    var height = img.height;      
    var width = img.width;      
    let maxWidth = 500;    
    let canvasWidth = width; //图片原始长宽    
    let canvasHeight = height;    
    let base = canvasWidth/canvasHeight;    
    console.log(maxWidth);    
    if(canvasWidth > maxWidth){    
        canvasWidth = maxWidth;    
        canvasHeight = Math.floor(canvasWidth/base);    
    }    
    width = canvasWidth;    
    height = canvasHeight;    
    var step = 0;      

    if (step == null) {      
      step = min_step;      
    }      

    if (direction == 'right') {     

      step += times;      
      //旋转到原位置,即超过最大值      
      step > max_step && (step = min_step);      
    } else if(direction == 'left'){      
      step -= times;      
      step < min_step && (step = max_step);      
    } else {    //不旋转    
        step = 0;    
    }    

    //旋转角度以弧度值为参数      
    var degree = step * 90 * Math.PI / 180;      
    var ctx = canvas.getContext('2d');      
    console.log(degree)    
    console.log(step)    
    switch (step) {        
      case 1:      

        console.log('右旋转 90度')    
        canvas.width = height;      
        canvas.height = width;      
        ctx.rotate(degree);      
        // ctx.drawImage(img, 0, 0, width, height);  
        ctx.drawImage(img, 0, -height, width, height);      
        break;      
      case 2:      
        //console.log('旋转 180度')    
        canvas.width = width;      
        canvas.height = height;      
        ctx.rotate(degree);      
        ctx.drawImage(img, -width, -height, width, height);      
        break;      
      case 3:      
        console.log('左旋转 90度')    
        canvas.width = height;      
        canvas.height = width;      
        ctx.rotate(degree);      
        ctx.drawImage(img, -width, 0, width, height);    
        break;      
      default:  //不旋转    
        canvas.width = width;    
        canvas.height = height;    
        ctx.drawImage(img, 0, 0, width, height);    
        break;    
    }    

    let baseStr = canvas.toDataURL("image/jpeg", 1);    
    return baseStr;    
}  

ios 系统版本13.4以上不需要进行图片旋转 ios 13.4以上竖拍 Orientation 依然会得到6 但是图片已经被系统调整到正常 使用旋转后会导致图片被旋转2次

//ios 13.4以上不需要进行翻转  
const getVersionRotate = ()  => {  
    var ua = navigator.userAgent.toLowerCase();  
    var ver= ua.match(/cpu iphone os (.*?) like mac os/);  
    let b = ver[1].replace(/_/g,".");  
    return toNum(b) >= toNum(13.4) ? false : true;  
}  
//计算版本号大小,转化大小  
const toNum = (a)  =>  {  
  var a=a.toString();  
  var c=a.split('.');  
  var num_place=["","0","00","000","0000"],r=num_place.reverse();  
  for (var i=0;i<c.length;i++){   
     var len=c[i].length;         
     c[i]=r[len]+c[i];    
  }   
  var res= c.join('');   
  return res;   
}   

// #ifndef APP-PLUS  

 //处理图片旋转 H5上传入口  
 if(getVersionRotate()) {  
     _file = await rotatePic (filePath, dir) || filePath;  
 }  

 // #endif

原生图片旋转解决思路

因为几个测试机未出现图片旋转问题,所以未进行旋转,解决思路为选择图片后 uni.getImageInfo(OBJECT) success中获取orientation 旋转参数,使用plus.zip.compressImage进行原生图片旋转

0 关注 分享

要回复文章请先登录注册

FullStack

FullStack

获取修改图片Exif信息(ios、andorid):[https://ext.dcloud.net.cn/plugin?id=9190](https://ext.dcloud.net.cn/plugin?id=9190)
2022-08-24 16:32
风云杭州

风云杭州

app端的异步有点麻烦,目前还是通过在服务器端,用 php的exif和图片处理相关函数来解决 图片方向的问题
2020-12-10 01:52
落魄前端

落魄前端

app端 旋转图片

getImageInfo(src) {
return new Promise((ressolve,resject)=>{
uni.getImageInfo({
src: src,
success: (image) =>{
if(image.orientation == 'right') {
// 顺时针旋转90度
plus.zip.compressImage( {
rotate: 90 ,
src: image.path,
dst: image.path.substring(image.path.lastIndexOf('/'),image.path.length - 1) ,
}, (e)=>{
ressolve(e.target)
}, (err)=>{
ressolve(image.path)
});
} else {
ressolve(image.path)
}
}
});
})
}
2020-09-07 13:52