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

HTML Canvas中setTransform后点击坐标转换问题求助

解决Canvas水平翻转后的点击坐标转换问题

当你通过setTransform做水平翻转(通常是ctx.setTransform(-1, 0, 0, 1, canvas.width, 0)这类矩阵)时,画布的坐标系统被反转——原本X轴正方向从左到右变为从右到左,同时为了让内容显示在画布内,做了等同于画布宽度的X轴平移。要把点击事件的坐标转换回原始绘制坐标,只需做简单的反向计算:

坐标转换逻辑

  • 假设点击事件拿到的x、y是相对于画布内部的坐标(HMI环境直接提供)
  • 原始绘制X坐标 = 画布宽度 - 点击X坐标
  • 原始绘制Y坐标 = 点击Y坐标(水平翻转不影响Y轴)

代码实现示例

const canvas = document.getElementById('yourCanvas');
const ctx = canvas.getContext('2d');
let highlightedRect = null;

// 初始化绘制(带水平翻转)
function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  // 应用水平翻转变换
  ctx.setTransform(-1, 0, 0, 1, canvas.width, 0);
  
  // 绘制原始对象(示例矩形)
  const rect = { x: 50, y: 50, width: 100, height: 100 };
  ctx.fillStyle = highlightedRect === rect ? '#ff0000' : '#00ff00';
  ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
  
  // 重置变换(可选,不影响后续检测)
  ctx.setTransform(1, 0, 0, 1, 0, 0);
}

// 点击事件处理
canvas.addEventListener('click', function(e) {
  // 获取HMI提供的画布内点击坐标
  const clickX = e.x;
  const clickY = e.y;
  const canvasWidth = canvas.width;
  
  // 转换为原始坐标
  const originalX = canvasWidth - clickX;
  const originalY = clickY;
  
  // 检测是否命中目标对象
  const targetRect = { x: 50, y: 50, width: 100, height: 100 };
  if (originalX >= targetRect.x && originalX <= targetRect.x + targetRect.width &&
      originalY >= targetRect.y && originalY <= targetRect.y + targetRect.height) {
    highlightedRect = targetRect;
  } else {
    highlightedRect = null;
  }
  draw(); // 重新绘制以显示高亮
});

// 初始绘制
draw();

原理说明

水平翻转的变换矩阵(-1, 0, 0, 1, canvas.width, 0)对每个绘制点的坐标计算规则是:
绘制后X = -原始X + 画布宽度
绘制后Y = 原始Y

反过来推导,已知绘制后的点击X坐标,就能算出原始X坐标:原始X = 画布宽度 - 绘制后X,Y坐标不受影响直接沿用。

如果后续用到更复杂的变换(比如同时缩放、旋转),可以通过计算变换矩阵的逆矩阵来完成坐标转换,但针对当前的水平翻转场景,上面的简化计算完全足够。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 12:22:24