Svelte Canvas缩放平移后,修正坐标实现光标处画线
解决Canvas缩放平移后画线光标偏移问题
问题根源是绘制时未将屏幕光标坐标转换为Canvas变换后的逻辑坐标。你的Canvas已经通过trackTransforms实现了坐标变换能力,但绘制代码直接使用原始屏幕坐标,导致线条位置与光标偏离。
修改关键代码
只需要调整handleStart和handleMove函数,利用已有的transformedPoint方法转换坐标:
const handleStart = ({ offsetX: x, offsetY: y }) => { isDrawing = true; // 将屏幕坐标转换为Canvas变换后的逻辑坐标 const transformedPt = ctx.transformedPoint(x, y); start = { x: transformedPt.x, y: transformedPt.y }; }; const handleMove = (event) => { if (!isDrawing) return; // 直接使用已声明的ctx,无需重新获取 const { offsetX: x, offsetY: y } = event; // 转换当前光标坐标 const currentPt = ctx.transformedPoint(x, y); const { x: startX, y: startY } = start; ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(currentPt.x, currentPt.y); ctx.stroke(); // 更新起始点为转换后的坐标 start = { x: currentPt.x, y: currentPt.y }; };
核心修改点说明
- 坐标转换:使用
ctx.transformedPoint(x, y)将屏幕上的offsetX/offsetY转换为Canvas经过缩放、平移后的逻辑坐标,确保绘制位置与光标匹配。 - 复用上下文:直接使用已初始化的
ctx变量,避免重复调用getContext造成的性能浪费和潜在问题。 - 更新起始点:每次绘制后,将起始点更新为转换后的当前坐标,保证连续绘制的线条连贯。
额外优化建议
- 移除
handleMove中重复获取canvas和context的代码,直接使用组件内已声明的变量。 - 若需要保留绘制的线条(当前平移/缩放会清空线条),可将线条路径记录在数组中,在
redraw函数里循环重绘所有路径。
内容的提问来源于stack exchange,提问作者R.alim
相关产品推荐
相关产品推荐

