画布缩放后元素位置偏移怎么办?
我在做一个可视化编辑器,用 canvas 实现的画布。当用户滚动鼠标滚轮缩放画布时,我通过 ctx.scale(scale, scale) 来缩放,但发现拖拽元素时位置明显偏移了,好像没考虑当前缩放比例。
我试过在计算鼠标坐标时除以 scale,但还是不对。比如下面这段处理鼠标坐标的代码:
const rect = canvas.getBoundingClientRect();
const x = (event.clientX - rect.left) / scale;
const y = (event.clientY - rect.top) / scale;
可拖拽的时候元素还是会“跳”一下,感觉哪里漏了?是不是还要考虑平移(translate)的影响?
当你同时使用了 translate 和 scale 时,鼠标坐标要经过这两个变换的逆运算。正确做法是:
这里 translateX 和 translateY 就是你调用 ctx.translate(tx, ty) 时传入的值。
另外提醒一点,拖拽元素更新位置时,移动量也要乘以 scale:
如果你用的是现代浏览器(Chrome 90+),可以用更优雅的方式:
这样就不用手动维护 translateX 和 translateY 了,浏览器会帮你算好逆矩阵。