微信小程序,web,uniapp-vue前端图片压缩思路-------uniapp-nvue如何压缩----
uniapp官方提供的压缩接口,只支持jpg的压缩,所以,直接放弃
在非nvue的页面中,统一使用canvas获取图片信息,并重新绘制。
存在一个问题,canvas必须指定宽高,不能动态给定,所以可能存在一些问题。
nvue页面,又无法使用canvas,或者说,性能不是很好。
一个隐藏的canvas只做图片处理使用,应该不会影响实际的界面效果。
参考博客
微信小程序-上传压缩图片和视频
https://www.cnblogs.com/wq805/p/16278113.html
h5和pc端
移动端——Uni-app 使用 Cavans 压缩图片插件。但是压缩之后,怎么图片大小变大了。
https://blog.51cto.com/marsxh/3823492
canvas压缩图片画的很模糊啊
Canvas清晰度的问题
https://blog.csdn.net/BrianV530/article/details/135103007
让canvas画布和图片大小宽高一致,并且不使用rpx
最终的实现方式。使用压缩组件
<template>
<view class="compress">
<canvas :style="{ width: canvasSize.width,height: canvasSize.height}" canvas-id="myCanvas"></canvas>
</view>
</template>
<script>
export default {
data() {
return {
canvasSize: {
width: '0px',
height: '0px'
}
}
},
methods: {
// 压缩
compress(params) {
return new Promise(async (resolve, reject) => {
// 等待图片信息
let info = await this.getImageInfo(params.src).then(info=>info).catch(err=>err);
if(!info){
reject('获取图片信息异常');
return;
}
// 设置最大 & 最小 尺寸
const maxSize = params.maxSize || 1600;
const minSize = params.minSize || 0;
// 当前图片尺寸
let {width,height} = info;
// 非 H5 平台进行最小尺寸校验
// #ifndef H5
if(width <= minSize && height <= minSize){
resolve(params.src);
return;
}
// #endif
// 最大尺寸计算
if (width > maxSize || height > maxSize) {
if (width > height) {
height = Math.floor(height / (width / maxSize));
width = maxSize;
} else {
width = Math.floor(width / (height / maxSize));
height = maxSize;
}
}
// 设置画布尺寸
this.$set(this,"canvasSize",{
width: `${width}px`,
height: `${height}px`
});
console.log('xiaocheng1')
// Vue.nextTick 回调在 App 有异常,则使用 setTimeout 等待DOM更新
setTimeout(() => {
const ctx = uni.createCanvasContext('myCanvas', this);
ctx.clearRect(0,0,width, height)
ctx.drawImage(info.path, 0, 0, width, height);
ctx.draw(false, () => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: width,
height: height,
destWidth: width,
destHeight: height,
canvasId: 'myCanvas',
fileType: params.fileType || 'jpg',
quality: params.quality || 0.8,
success: (res) => {
let resultPath = res.tempFilePath
// 在H5平台下,tempFilePath 为 base64 需转换为 path
// #ifdef H5
const base64Code = this.dataURLtoBlob(resultPath)
resultPath = URL.createObjectURL(base64Code)
// #endif
resolve(resultPath);
},
fail:(err)=>{
console.log('fail', err)
reject(null);
}
},this);
});
}, 300);
});
},
dataURLtoBlob(dataurl) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n) //8位无符号整数,长度1个字节
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], {
type: mime,
})
},
// 获取图片信息
getImageInfo(src){
return new Promise((resolve, reject)=>{
uni.getImageInfo({
src,
success: (info)=> {
resolve(info);
},
fail: () => {
reject(null);
}
});
});
}
}
}
</script>
<style scoped>
.compress{
position: fixed;
width: 12px;
height: 12px;
overflow: hidden;
top: -99999px;
bottom: 0;
}
</style>
组件的使用方法
<compress ref="compress" />
import compress from '@/components/compress.vue'
components: { compress }
// 在需要压缩时调用
uni.chooseImage({
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
// compress
const compressParams = {
src: tempFilePaths[0] // 必选: 要压缩的图片地址
}
this.$refs.compress.compress(compressParams).then(filePath => {
uni.uploadFile({
url: baseUrl + '/upload',
filePath: filePath,
name: 'file',
success: (uploadFileRes) => {}
})
})
}
})