前段时间写过一次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
)
			}
		})
	})
}