2024-05-10  2024-05-10    640 字  2 分钟

使用场景

需要将一张图片自适应到一个长度、宽度固定的容器中、且充满整个容器,但不希望压缩图片。在实际中,我们可以通过设置 div 标签的 background-size: cover; 来实现,也可以通过设置 img 标签的 object-fit: cover; 来实现。有一种场景,想要将图片裁剪成cover的样子导出为base64作为其他用处,以上两种方式就很难实现。

解决方案

一种简单的实现方式,可以通过 html2Cavans 包将 div 或者 img 标签调整好的图片大小做一个快照保存成 cavans 来导出。本质上可以直接使用 canvas 来实现该功能,基本的原理是将图片等比例放大,然后定位图片在 cavans 中的绘制起点位置。实现逻辑:

  1. 创建一个目标大小的 cavans 标签。
  2. 计算图片和 cavans 的最大缩放比例,等于宽和高的缩放比例的最大值。
  3. 计算图片缩放后的宽和高。
  4. 计算 cavans (0, 0)坐标对应图片的坐标点,也就是起点的偏移位置。
  5. 调用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());
        };
    });
}