前段时间写过一次h5利用canvas压缩图片的方法,本以为小程序压缩也大同小异,结果不慎掉入坑中爬了好久,这里以uniapp 为例总结一下: canvas压缩多张图片(一) canvas压缩多张图片(二)
上传图片 chooseImage
这里要和h5利用input 上传不同,这里需要利用chooseImage上传图片
uni
.chooseImage({
count
: 9,
sourceType
: ['album','camera'],
sizeType
: ['compressed'],
success(res
) {
if(res
.errMsg
=='chooseImage:ok'){
that
.urlTobase64Fn(res
.tempFilePaths
)
}
}
})
遍历图片数据,进行压缩处理 ,记得要加 id 和 this
async urlTobase64Fn (arr
){
for(let i
=0;i
<arr
.length
;i
++){
let base64
=await urlTobase64(arr
[i
],"canvasId",this);
this.imgArr
.push(base64
)
}
},
<canvas id
="canvasId" class="canvasId" canvas
-id
="canvasId" ></canvas
>
.canvasId
{
position
: absolute
;
top
:-9999rpx
;
left
: -9999rpx
;
z
-index
: 0;
width
: 690rpx
;
height
: 690rpx
;
}
对URL进行处理 urlTobase64 (这是自定义的方法)
urlTobase64
= async (fileObj
,_this
)=>{
let type
=fileObj
.type
|| fileObj
.path
.substring(fileObj
.path
.lastIndexOf('.')+1);
let base64
= await getFileSystemManagerFn({
path
:fileObj
.path
,
type
});
base64
= base64
.replace(/[\r\n]/g, "");
if(type
=='mp4'){
console
.log('是视频,直接输出base64')
return fileObj
.fileType
=='video'?base64
: ''
}
let imgSize
= await getBase64SizeFn(base64
);
console
.log(imgSize
,'是图片,判断图片大小');
fileObj
.limitNum
= fileObj
.limitNum
|| 1024 *0.2;
if(imgSize
>fileObj
.limitNum
&& type
!='gif'){
console
.log(imgSize
,'需要压缩')
let imgInfo
= await getImageInfoFn (fileObj
.path
);
fileObj
.canvasId
= fileObj
.canvasId
|| 'canvasId';
return await convertImgToBase64Fn({
...fileObj
,
oldH
: imgInfo
.height
,
oldW
: imgInfo
.width
,
type
: imgInfo
.type
},_this
);
} else {
console
.log(imgSize
,'可以直接使用');
return base64
}
},
convertImgToBase64Fn
= async (obj
,_this
) =>{
obj
.minW
= obj
.minW
|| 750,
obj
.minH
= obj
.minH
|| 1334;
obj
.num
= obj
.num
|| 1;
var cvsw
,cvsh
;
if(obj
.oldW
> obj
.oldH
){
cvsh
= obj
.oldH
> obj
.minH
? obj
.minH
: obj
.oldH
;
cvsw
= cvsh
/ obj
.oldH
* obj
.oldW
}
else if(obj
.oldW
< obj
.oldH
){
cvsw
= obj
.oldW
> obj
.minW
? obj
.minW
: obj
.oldW
;
cvsh
= cvsw
/ obj
.oldW
* obj
.oldH
}
else if(obj
.oldW
== obj
.oldH
&& obj
.oldW
> obj
.minW
){
cvsw
= obj
.minW
;
cvsh
= obj
.minH
;
}
else {
cvsw
= obj
.oldW
;
cvsh
= obj
.oldH
;
}
cvsw
= parseInt(cvsw
);
cvsh
= parseInt(cvsh
);
console
.log(cvsw
,cvsh
,'设置canvas画布大小');
_this
.windowInfo
={
width
:cvsw
,
height
:cvsh
}
let dataURL
= await canvasToTempFilePathFn({...obj
,cvsw
,cvsh
},_this
);
console
.log(dataURL
.substring(0,50),'输出压缩后最终地址')
return dataURL
;
},
getBase64SizeFn =(base64url
) =>{
var strLength
=base64url
.length
;
var fileLength
= parseInt(strLength
- (strLength
/ 8) * 2);
var size
= "";
size
= (fileLength
/ 1024).toFixed(2);
return parseInt(size
) *1;
},
getImageInfoFn = (url
)=>{
console
.log(url
,'去获取图片信息')
return new Promise((resolve
)=>{
wx
.getImageInfo({
src
: url
,
success
: (res
)=> {
console
.log(res
.path
,'图片信息')
resolve(res
)
}
});
})
},
canvasToTempFilePathFn =(obj
,_this
)=>{
return new Promise((resolve
,reject
)=>{
const ctx
= uni
.createCanvasContext(obj
.canvasId
,_this
);
console
.log(obj
.num
,obj
.type
,'压缩开始')
ctx
.drawImage(obj
.path
, 0, 0, obj
.cvsw
, obj
.cvsh
);
ctx
.draw(false, setTimeout(()=>{
uni
.canvasToTempFilePath({
canvasId
:obj
.canvasId
,
fileType
:obj
.type
,
quality
:obj
.num
,
width
:obj
.cvsw
,
height
:obj
.cvsh
,
destWidth
:obj
.cvsw
,
destHeight
:obj
.cvsh
,
success
: async (res1
) =>{
console
.log('去将压缩后的地址转base64')
let base64
= await getFileSystemManagerFn({
path
:res1
.tempFilePath
,
type
:obj
.type
});
base64
= base64
.replace(/[\r\n]/g, "");
console
.log('去后去压缩后的base64大小')
let imgSize
= getBase64SizeFn(base64
);
if( imgSize
>= obj
.limitNum
&& obj
.num
>0.6){
console
.log(imgSize
,'图片过大,继续压缩')
obj
.num
= obj
.num
- 0.2 ;
obj
.num
= obj
.num
.toFixed(2) *1;
if(obj
.type
=='png' || obj
.type
=='PNG'){
obj
.type
='png'
} else{
obj
.type
='jpg'
}
canvasToTempFilePathFn({...obj
},_this
).then((res2
)=>{
resolve(res2
)
});
} else{
console
.log(imgSize
,'最终压缩后图片大小')
resolve(base64
)
}
},
fail
: function (e
) {
console
.log('失败')
reject(e
)
}
},_this
)
},200));
})
},
getFileSystemManagerFn =(obj
)=>{
return new Promise(async (resolve
,reject
)=>{
let path
= obj
.path
;
if(path
.indexOf('https://wx.qlogo.cn') >=0){
path
= await downloadFileFn(path
);
}
wx
.getFileSystemManager().readFile({
filePath
:path
,
encoding
:'base64',
success
: async res
=>{
console
.log(obj
.type
,'图片类型')
let base64
=`data:image/${obj.type};base64,${res.data}`;
resolve(base64
)
}
});
})
},
downloadFileFn =(url
)=>{
return new Promise ((resolve
,reject
)=>{
wx
.downloadFile({
url
,
success(res
) {
resolve(res
.tempFilePath
)
},
fail
:err
=>{
reject(err
)
}
})
})
}