之前写过一篇使用命令行工具压缩图片的博文:使用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 string
setTimeout(() => {
const { width, height } = img
const canvas = document.createElement('canvas') as HTMLCanvasElement
canvas.width = width
canvas.height = height
const 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 HTMLInputElement
input.addEventListener('input', inputChange)
function inputChange(evt: Event) {
const file = (evt.target as HTMLInputElement).files?.[0] as File
console.log(file.size, '原图片的大小--->>')
compressJpg(file, 0.1).then(blob => {
if(!blob) return
console.log(blob.size, '压缩后的大小--->>')
})
}
这是控制台的打印,可见确实是图片的大小小了很多,但其实看图片模糊了很多。
总结一下:
1. 从上面能看出来在牺牲一些清晰度的情况下,用这种方式压缩还是可以的,特别是一些本身就比较小的图片,但其实这并不是真正的压缩图片,真正压缩图片还是建议使用工具压缩,例如photoshop;或者在线网站压缩,例如:熊猫压缩
2. 大家可以看到我的方法名为:compressJpg 之所以取这个方法名,是因为此方式其实仅支持jpg格式的图片压缩,如果是png格式,可能还会变大,大家可以测试一下,再对比一下图片质量