如何在带变换的CanvasRenderingContext2D中检测鼠标悬停元素
解决Canvas变换后的鼠标悬停检测问题
你可以利用Canvas的变换矩阵逆运算,直接将屏幕鼠标坐标转换为Canvas本地坐标系的坐标,这种方法能自动适配所有变换(平移、缩放、旋转等),比手动跟踪变换参数简洁得多。
核心逻辑
- 获取Canvas当前的变换矩阵,通过
ctx.getTransform()实现; - 对变换矩阵求逆,得到逆变换矩阵——这个矩阵可以把屏幕坐标“还原”为Canvas本地坐标系的坐标;
- 用逆矩阵转换鼠标的屏幕位置,之后就能直接在本地坐标系里计算鼠标与元素的距离。
修改后的代码
const ctx = canv.getContext('2d'); // 设置Canvas尺寸(示例值,可按需调整) canv.width = 400; canv.height = 300; // 绘制背景 ctx.fillStyle = '#000'; ctx.fillRect(0, 0, canv.width, canv.height); // 应用组合变换:平移到中心 + 缩放(演示适配性) ctx.translate(canv.width / 2, canv.height / 2); ctx.scale(2, 2); // 绘制中心正方形(本地坐标(0,0)为中心) ctx.fillStyle = 'yellow'; ctx.fillRect(-4, -4, 8, 8); canv.addEventListener('mousemove', event => { // 1. 获取鼠标相对于Canvas的原始坐标 const mouseScreenX = event.offsetX; const mouseScreenY = event.offsetY; // 2. 获取当前变换矩阵并求逆 const transform = ctx.getTransform(); const inverseTransform = transform.invertSelf(); // 3. 用逆矩阵转换鼠标坐标到本地坐标系 const mouseLocal = inverseTransform.transformPoint(new DOMPoint(mouseScreenX, mouseScreenY)); // 4. 计算到元素中心(0,0)的距离 const distance = Math.sqrt(mouseLocal.x ** 2 + mouseLocal.y ** 2); coord.innerText = `Distance to square: ${distance.toFixed(2)}`; });
<canvas id="canv"></canvas> <div id="coord"></div>
优势说明
- 无需手动跟踪所有变换操作(比如多次平移、缩放叠加),矩阵运算会自动处理所有组合变换;
- 代码逻辑通用,后续添加旋转(
ctx.rotate())等其他变换时,无需修改鼠标检测部分的代码; - 计算结果精准,避免手动计算变换时可能出现的误差。
内容的提问来源于stack exchange,提问作者SteeveDroz
相关产品推荐
相关产品推荐

