【uni-app】 拍照图片旋转bug以及解决方法

3,573 阅读2分钟

前言:


目前测试图片旋转只会出现在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进行原生图片旋转