使用场景
需要将一张图片自适应到一个长度、宽度固定的容器中、且充满整个容器,但不希望压缩图片。在实际中,我们可以通过设置 div
标签的 background-size: cover;
来实现,也可以通过设置 img
标签的 object-fit: cover;
来实现。有一种场景,想要将图片裁剪成cover的样子导出为base64
作为其他用处,以上两种方式就很难实现。
解决方案
一种简单的实现方式,可以通过 html2Cavans
包将 div
或者 img
标签调整好的图片大小做一个快照保存成 cavans
来导出。本质上可以直接使用 canvas
来实现该功能,基本的原理是将图片等比例放大,然后定位图片在 cavans
中的绘制起点位置。实现逻辑:
- 创建一个目标大小的
cavans
标签。 - 计算图片和
cavans
的最大缩放比例,等于宽和高的缩放比例的最大值。 - 计算图片缩放后的宽和高。
- 计算
cavans
(0, 0)坐标对应图片的坐标点,也就是起点的偏移位置。 - 调用
cavans
的绘制方法,将图片、起点偏移信息、缩放后的宽高传进去绘制,最后导出base64
即可。
代码实现
/**
* 以cover的方式改变图片的大小
* @param {string} src 图片
* @param {number} targetWidth 目标图片的宽度
* @param {number} targetHeight 目标图片的高度
*/
changeImage(src: string, targetWidth: number, targetHeight: number) {
return new Promise((resolve) => {
// 创建一个canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 加载图片资源
const img = new Image();
img.src = src;
img.onload = function () {
const canvasWidth = targetWidth; // 设置 Canvas 的固定宽度
const canvasHeight = targetHeight; // 设置 Canvas 的固定高度
canvas.width = canvasWidth;
canvas.height = canvasHeight;
const scaleX = canvasWidth / img.width; // 计算横向缩放比例
const scaleY = canvasHeight / img.height; // 计算纵向缩放比例
const scale = Math.max(scaleX, scaleY); // 取最大的缩放比例
const scaledWidth = img.width * scale; // 计算缩放后的宽度
const scaledHeight = img.height * scale; // 计算缩放后的高度
const offsetX = (canvasWidth - scaledWidth) / 2; // 计算图片在 Canvas 中的横向偏移量
const offsetY = (canvasHeight - scaledHeight) / 2; // 计算图片在 Canvas 中的纵向偏移量
//绘制图片并导出
ctx.drawImage(img, offsetX, offsetY, scaledWidth, scaledHeight);
resolve(canvas.toDataURL());
};
});
}