之前写过一篇使用命令行工具压缩图片的博文:使用yx-tiny命令行工具进行图片压缩,大家感兴趣可以去瞅一眼。
这篇简单说一下使用canvas压缩图片
其实思路很简单,我们选择了图片之后,会获取到对应的文件流对象,然后我们将这个文件流再转为图片,然后使用canvas将这个图片画出来,最后调用canvas.toDataURL 或者 canvas.toBlob 方法传入对应的参数来实现图片的压缩,下面是压缩图片的方法:
function compressJpg(file: File, quality: number = 0.5): Promise<Blob | null> {return new Promise((resolve, reject) => {if(!file.name.endsWith('.jpg') && !file.name.endsWith('jpeg')) {return reject('仅支持JPG格式图片压缩')}try {const img = new Image()const fr = new FileReader()fr.readAsDataURL(file)fr.onload = e => {img.src = e.target?.result as stringsetTimeout(() => {const { width, height } = imgconst canvas = document.createElement('canvas') as HTMLCanvasElementcanvas.width = widthcanvas.height = heightconst ctx = canvas.getContext('2d')ctx?.drawImage(img, 0, 0, width, height)canvas.toBlob(blob => {resolve(blob)}, file.type, quality)})}} catch(e) {reject(e)}})
}
我们传入一个要压缩的文件对象和质量参数,返回一个Promise,then中可以获取到压缩后的文件对象。
下面测试一下:
const input = document.getElementById('input') as HTMLInputElementinput.addEventListener('input', inputChange)function inputChange(evt: Event) {const file = (evt.target as HTMLInputElement).files?.[0] as Fileconsole.log(file.size, '原图片的大小--->>')compressJpg(file, 0.1).then(blob => {if(!blob) returnconsole.log(blob.size, '压缩后的大小--->>')})
}
这是控制台的打印,可见确实是图片的大小小了很多,但其实看图片模糊了很多。
总结一下:
1. 从上面能看出来在牺牲一些清晰度的情况下,用这种方式压缩还是可以的,特别是一些本身就比较小的图片,但其实这并不是真正的压缩图片,真正压缩图片还是建议使用工具压缩,例如photoshop;或者在线网站压缩,例如:熊猫压缩
2. 大家可以看到我的方法名为:compressJpg 之所以取这个方法名,是因为此方式其实仅支持jpg格式的图片压缩,如果是png格式,可能还会变大,大家可以测试一下,再对比一下图片质量