lh1me

Canvas 图片绘制完全覆盖铺满效果

问题

最近在需求中需要将用户照片绘制成海报,遇到需要将照片以保持宽高的情况绘制在一个相框内

解决

参照 background-size: cover 的效果

缩放背景图片以完全覆盖背景区,可能背景图片部分看不见。和 contain 值相反,cover 值尽可能大的缩放背景图像并保持图像的宽高比例(图像不会被压扁)。该背景图以它的全部宽或者高覆盖所在容器。当容器和背景图大小不同时,背景图的 左/右 或者 上/下 部分会被裁剪。

直接上代码理解就行了。

核心方法

getImageCoverSize(contentWidth, contentHeight, containerWidth, containerHeight, offsetLeft, offsetTop) {
    const contentRatio = contentWidth / contentHeight;
    const containerRatio = containerWidth / containerHeight;
    let resultHeight;
    let resultWidth;
    offsetLeft = typeof offsetLeft === 'undefined' ? 0.5 : offsetLeft;
    offsetTop = typeof offsetTop === 'undefined' ? 0.5 : offsetTop;
    if (contentRatio > containerRatio) {
        resultHeight = containerHeight;
        resultWidth = containerHeight * contentRatio;
    } else {
        resultWidth = containerWidth;
        resultHeight = containerWidth / contentRatio;
    }
    return {
        width: resultWidth,
        height: resultHeight,
        offsetLeft: (containerWidth - resultWidth) * offsetLeft,
        offsetTop: (containerHeight - resultHeight) * offsetTop
    };
}

使用方式

handleClipImage(image) {
    const canvas = document.createElement('canvas');
    canvas.width = 200;
    canvas.height = 250;
    const ctx = canvas.getContext('2d');
    const imageCoverSize = getImageCoverSize(
        image.width,
        image.height,
        canvas.width,
        canvas.height,
        0.5,
        0.5
    );
    ctx.drawImage(
        image,
        imageCoverSize.offsetLeft,
        imageCoverSize.offsetTop,
        imageCoverSize.width,
        imageCoverSize.height
    );
    return canvas.toDataURL()
},

文章参考文献

@agilie/canvas-image-cover-position

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。