You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Konva getTransform矩阵按比例适配至高分辨率遮罩画布?

在线DIY相册Konva遮罩照片变换矩阵转换问题

我们开发的是在线DIY相册项目,需要用Konva实现类似Photoshop的遮罩效果——照片置于相框下方。由于画布中可能存在多个相框,我们采用独立遮罩画布(Canvas 2)绘制完成后,再导入Konva主画布(Canvas 1)中。

为支持用户对照片进行拖拽、旋转、缩放操作,我们在Canvas 1上绘制了与Canvas 2中照片尺寸、位置一致的透明矩形,并为其绑定Transformer。通过获取透明矩形的transform矩阵,将其应用到Canvas 2的照片上,以此实现两者的同步变换。

当Canvas 2与Canvas 1中最终绘制元素尺寸相同时,功能完全正常;但为保证清晰度,我们将Canvas 2的尺寸设置为主画布元素尺寸的5倍(1000*1000)后,拖拽或旋转透明矩形时,遮罩中的照片位置出现明显偏差。推测原因是透明元素与Canvas 2中照片尺寸不一致,需要对getTransform获取的矩阵进行转换,现寻求该矩阵的具体转换方法。

代码实现

// Canvas 1 主画布
let container = document.getElementById("container");
let stage = new Konva.Stage({
    container: container,
    width: 800,
    height: 800
});

layer = new Konva.Layer();
stage.add(layer);

let group = new Konva.Group({
    x: 100,
    y: 100,
    width: 200,
    height: 200,
    clipX: 0,
    clipY: 0,
    clipWidth: 200,
    clipHeight: 200
});

let shape = await drawMaskPhoto();
group.add(shape);

let transparentRect = new Konva.Rect({
    width: 200,
    height: 200,
    x:0,
    y:0,
    type:"transparentRect"
});
group.add(transparentRect);


transparentRect.on('transform',async function (e) {
    let transform = e.target.getTransform().m;
    shape = await drawMaskPhoto(transform);
});

function newImg(src) {
    return new Promise((resolve, reject) => {
        let img = new Image();
        img.src = src;
        img.onload = () => {
            resolve(img)
        }
    })
}

async function drawMaskPhoto(transform){
    // Canvas 2 遮罩画布
    let maskCanvas = document.createElement("canvas");
    let mask = await newImg(mask.imgPath);
    let photo = await newImg(photo.imgPath);
    // 为保证清晰度,将遮罩画布尺寸设为主画布元素的5倍(1000*1000)
    maskCanvas.width = 1000;
    maskCanvas.height = 1000;
    let ctx = maskCanvas.getContext("2d");
    ctx.drawImage(mask, 0, 0, 1000, 1000);
    ctx.globalCompositeOperation = 'source-atop';
    if(transform){
        ctx.setTransform(...transform);
    }
    ctx.drawImage(photo, 0, 0, 1000, 1000);
    
    let shape = new Konva.Image({
        image:maskCanvas,
        width:200,
        height:200
    })
    return shape
}

效果说明

  • 绘制效果:照片能正确显示在相框遮罩范围内
  • 旋转后效果:照片位置偏移,无法匹配相框遮罩区域

内容的提问来源于stack exchange,提问作者wen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 05:01:01