如何将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
相关产品推荐
相关产品推荐

