实现原理
要想使用JS实现图片的压缩效果,核心API就是使用canvas
的drawImage()
方法。Canvas本质上就是一张位图,而drawImage()方法可以把一张大大的图片绘制在小小的Canvas画布上,不就等同于图片尺寸压缩了?对于本案例的压缩,使用的5个参数的API方法
context.drawImage(img, dx, dy);
context.drawImage(img, dx, dy, dWidth, dHeight);
context.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
img
就是图片对象,可以是页面上获取的DOM对象,也可以是虚拟DOM中的图片对象。
dx, dy, dWidth, dHeight
表示在canvas画布上规划处一片区域用来放置图片,dx, dy为canvas元素的左上角坐标,dWidth, dHeight指canvas元素上用在显示图片的区域大小。如果没有指定sx,sy,sWidth,sHeight这4个参数,则图片会被拉伸或缩放在这片区域内。
sx,sy,swidth,sheight
这4个坐标是针对图片元素的,表示图片在canvas画布上显示的大小和位置。sx,sy表示图片上sx,sy这个坐标作为左上角,然后往右下角的swidth,sheight尺寸范围图片作为最终在canvas上显示的图片内容。
drawImage()
drawImage()方法有一个非常怪异的地方,大家一定要注意,这里的drawImage()9个参数时候,可选参数sx,sy,swidth,sheight是在前面的。
下图为MDN上原理示意:
本文的图片压缩,需要用的是是5个参数语法。 一张图片(假设图片对象是img)的原始尺寸是originWidth *originHeight ,现要求尺寸最大宽度为500, 原理如下代码示意:
// 创建画布
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
// 获取图片宽高
const originWidth = that.width
const originHeight = that.height
// 最大宽度
const maxWidth = 500
let targetWidth = originWidth
let targetHeight = originHeight
// 超出之后进行处理
if (originWidth > maxWidth) {
targetWidth = maxWidth
targetHeight = Math.round(originHeight * (maxWidth / originWidth))
}
// 设置画布宽高
var anw = document.createAttribute("width");
anw.nodeValue = targetWidth;
var anh = document.createAttribute("height");
anh.nodeValue = targetHeight;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
//绘制图片
context.drawImage(that, 0, 0, targetWidth, targetHeight);
核心JS
把大图片画在一张小画布上,压缩就这么实现了。
context.drawImage(that, 0, 0, targetWidth, targetHeight);
三、上传或下载
上传图片或者下载图片,可以使用canvas.toDataURL()
或者canvas.toBlob()
方法先进行转换。
1. canvas.toDataURL()
语法如下:
canvas.toDataURL(mimeType, qualityArgument)
可以把画布转换成base64格式信息图像信息,纯字符的图片表示法。
其中:mimeType表示canvas导出来的base64图片的类型,默认是png格式,也即是默认值是’image/png’,我们也可以指定为jpg格式’image/jpeg’或者webp等格式。file对象中的file.type就是文件的mimeType类型,在转换时候正好可以直接拿来用(如