又更新了下,难搞,苹果手机有些版本会旋转有些版本不会,所以还要区别下,目前只知道最新版的不会旋转,就单独处理下,目前没有打包成苹果app,所以在苹果包上有没有问题还不确定
卡了将近两天才解决完,真是头大,根据网上的方法也是卡了好久,所以又特地整理了下
h5是通过拿到旋转的值,重新用canvas画图,所以在页面需要加入canvas 元素,其中用v-if的原因,是重复上传的话之前画的不会清空掉,所以用v-if来清空。还有canvas要设置height: 100vh;width: 100vw; 才可以把上传的图片完整的画出来。然后在外一层加上overflow: hidden;就行,下面的代码片段是自己封装的组件中的片段,因为有些需要优化的就不贴出来完整的代码
<view class="h-upload-img-content">
<view class="h-upload-img-content-input" @click="onChangeUpload" v-if="!imgSrc">
<text class="cross"></text>
<!--canvas 用来解决图片旋转的-->
<canvas canvas-id="uploadCanvas" class="upload-canvas" v-if="isCanvas"></canvas>
</view>
<view class="h-upload-img-content-img" v-if="imgSrc">
<view class="h-upload-img-content-icon" @click.stop="onDelImg()"><h-icon path="icon/close" width="40" height="40" /></view>
<h-lazy-img :src="imgSrc" mode="widthFix" preview></h-lazy-img>
</view>
</view>
import compressImage from '@/libs/imageUtil.js';
...
// 选择上传文件
onChangeUpload() {
if (this.limt && this.limt <= this.imgList) return uni.showToast({ title: `只能上传${this.limt}个文件`, icon: 'none' });
uni.chooseImage({
count: this.limt || 1,
success: res => {
if (res && res.tempFiles.length && res.tempFiles[0].size > 5 * 1024 * 1024) {
return uni.showToast({ title: '上傳圖片大小不能超過5M!', icon: 'none' });
}
this.compressImageHandler(res.tempFiles[0]);
}
});
},
// 解决有些图片会旋转的问题
async compressImageHandler(file) {
uni.showLoading({title: '上傳中...'});
this.isCanvas = true; //用来清空画布
const tempPath = await compressImage(file.path);
this.uploadFile({ file: tempPath });
this.isCanvas = false;
},
// 上传文件
async uploadFile(file) {
try {
let res = await this.$api.uploadFile(file);
uni.showToast({ title: res.msg, icon: 'none' });
this.imgSrc = res.url;
this.$emit('change', this.imgSrc);
} catch (e) {
uni.showToast({ title: e.msg, icon: 'none' });
}
},
注意:h5因为要拿到旋转的值,所以引用exif.js文件,这个直接在github就可以搜到,但因为img中complete这个值我拿不到,所以把js文件的974行一段条件注释掉了。
解决旋转问题的js - imageUtil.js
/**
* imageUtil.js
*解决图片旋转的问题
* **/
import EXIF from './exif.js'
async function compressImage(path) {
let imageInfo = await getImageInfo(path)
let systemInfo = await getSystemInfo()
return new Promise(function(resolve, reject) {
// #ifdef APP-PLUS || APP-NVUE
appCompressImage(path, imageInfo).then(res => {
resolve(res)
}).catch(e => {
reject(e)
})
// #endif
// #ifdef H5
let orientation = 1;
let img = document.createElement("img");
img.src = path;
img.onload = function() {
EXIF.getData(img, function() {
orientation = EXIF.getTag(this, 'Orientation');
canvasImg(path, orientation, imageInfo, systemInfo).then(res => {
resolve(res)
}).catch(e => {
reject(e)
})
})
}
img.onerror = function() {
reject(path)
}
// #endif
})
}
// app处理旋转图片
function appCompressImage(src, imageInfo) {
return new Promise(function(resolve, reject) {
let orientation = imageInfo.orientation;
let rotate = 0;
let quality = 80;
if (plus.os.name == "iOS") {
rotate = 0;
quality = 25;
} else {
switch (orientation) {
case 'up': //exif:1 不旋转
rotate = 0;
break;
case 'down': //exif:3 旋转180度
rotate = 180;
break;
case 'right': //exif:6 旋转90度
rotate = 90;
break;
case 'left': //exif:8 旋转270度
rotate = 270;
break;
default:
rotate = 0;
break;
}
}
plus.zip.compressImage({
src: src,
dst: "_doc/uniapp_temp" + '/compressed/' + Math.round(new Date()) + '.png',
format: 'png',
quality: quality,
width: 'auto',
height: 'auto',
rotate: rotate,
},
function(event) {
resolve(event.target)
},
function(error) {
reject(src);
});
})
}
// 画图片
function canvasImg(path, or, imageInfo, systemInfo) {
return new Promise(function(resolve, reject) {
let canvasId = 'uploadCanvas'
const ctx = uni.createCanvasContext(canvasId)
let scale = imageInfo.width / imageInfo.height
// 图片参数 start
let maxdestWidth = 1100 // 2000;
let destWidth = imageInfo.width;
let destHeight = imageInfo.height;
let destCompressWidth = imageInfo.width;
let destCompressHeight = imageInfo.height;
// 压缩图片 最大不超过5M 1200
// 当宽大于高的时候
if (imageInfo.width > imageInfo.height) {
if (imageInfo.width > maxdestWidth) {
destCompressWidth = maxdestWidth;
destCompressHeight = Math.floor(destCompressWidth / scale);
} else {
destCompressWidth = imageInfo.width * 8 / 10;
destCompressHeight = Math.floor(destCompressWidth / scale);
}
}
// 当高大于宽
else {
if (imageInfo.height > maxdestWidth) {
destCompressHeight = maxdestWidth;
destCompressWidth = Math.floor(destCompressHeight * scale);
} else {
destCompressHeight = imageInfo.height * 0.8;
destCompressWidth = Math.floor(destCompressHeight * scale);
}
}
destWidth = destCompressHeight
destHeight = destCompressWidth
// 图片参数 end
// 画布参数 start
let maxWidth = 300;
let canvasW = imageInfo.width;
let canvasH = imageInfo.height;
let width = imageInfo.width;
let height = imageInfo.height;
// canvas画布不能超过最大宽
if (canvasW > maxWidth) {
canvasW = maxWidth;
canvasH = Math.floor(canvasW / scale);
}
width = canvasW
height = canvasH
// 画布参数 end
// console.log('--or---', or)
//单独处理苹果最新版本
if (systemInfo.model == 'iPhone' && systemInfo.system.indexOf('13.4.1') > -1) {
ctx.drawImage(path, 0, 0, canvasW, canvasH)
destWidth = destCompressWidth
destHeight = destCompressHeight
} else {
if (or == 6) { //逆时针旋转了90
ctx.translate(width, 0)
ctx.rotate(Math.PI / 2)
ctx.drawImage(path, 0, 0, canvasH, canvasW)
} else if (or == 3) { //逆时针旋转了180
ctx.translate(width, height)
ctx.rotate(Math.PI)
ctx.drawImage(path, 0, 0, canvasH, canvasW)
} else if (or == 8) { //顺时针旋转90
ctx.translate(0, height)
ctx.rotate(-Math.PI / 2)
ctx.drawImage(path, 0, 0, canvasH, canvasW)
} else {
ctx.drawImage(path, 0, 0, canvasW, canvasH)
// return resolve(path);
destWidth = destCompressWidth
destHeight = destCompressHeight
}
}
// console.log('图片原始长宽', imageInfo, maxWidth, canvasW, canvasH, width, height, destWidth, destHeight);
ctx.draw(true, setTimeout(() => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: width, //画布宽度
height: height,
destWidth: destWidth,
destHeight: destHeight,
fileType: 'png',
canvasId: canvasId,
success: (res) => {
resolve(res.tempFilePath)
},
fail: (err) => {
resolve(path);
}
})
}, 200))
})
}
// 获取图片信息
function getImageInfo(path) {
return new Promise(function(resolve, reject) {
// #ifdef APP-PLUS
plus.io.getImageInfo({
src: path,
success: function(image) {
// console.log('orientation=' + image.orientation);
resolve(image)
},
fail: function(err) {
console.log("getImageInfoErr: " + JSON.stringify(err));
reject(err)
}
});
// #endif
// #ifdef H5 || MP-WEIXIN
uni.getImageInfo({
src: path,
success: function(image) {
// console.log('orientation=' + image.orientation);
resolve(image)
},
fail: function(err) {
console.log("getImageInfoErr: " + JSON.stringify(err));
reject(err)
}
});
// #endif
});
}
// 获取系统信息
function getSystemInfo(path) {
return new Promise(function(resolve, reject) {
uni.getSystemInfo({
success(res) {
resolve(res)
},
fail(err) {
console.log("getSystemInfoErr: " + JSON.stringify(err));
reject(err)
}
});
});
}
export default compressImage
还有要注意的点,在ios中上传的方法设置这个才上传成功
题外话,原本没处理的图片地址是一个url,我以为还要把canvas之后的base64的格式转化成url才可以上传,然而其实可以直接base64上传,当时一时没转过弯,那叫一个尴尬呀。。。