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

Canvas 30度等距网格鼠标坐标转瓦片坐标问题求解

30度等距网格鼠标悬停瓦片识别方案

你的坐标转换问题不需要试错调参,直接对现有正向投影公式做逆矩阵求解,就能得到100%匹配的反向转换逻辑,完全适配你保留√3系数的30度视角要求。


实现原理

你当前使用的正向笛卡尔坐标转等距画布坐标公式是线性变换,对应二元一次方程组:

设原始平面网格坐标为 (cartX, cartY),投影后的画布坐标为 (isoX, isoY)

isoX = (cartX - cartY) * (√3 / 2) + canvasOffset
isoY = (cartX + cartY) / 2

直接解这个方程组求cartX和cartY,就能得到精确的反向转换公式,不需要手动猜系数位置:

cartX = (isoX - canvasOffset) / √3 + isoY
cartY = isoY - (isoX - canvasOffset) / √3

可直接使用的代码

1. 基础坐标转换函数

和你现有carToIso函数完全对称,无精度损失:

// 等距画布坐标转原始平面网格坐标(连续像素值)
function isoToCar(isoX, isoY) {
  const cos30 = Math.sqrt(3) / 2; // 和正向投影的角度参数完全一致
  const xDelta = isoX - canvasOffset;
  const cartX = xDelta / (2 * cos30) + isoY;
  const cartY = isoY - xDelta / (2 * cos30);
  return [cartX, cartY];
}

2. 鼠标悬停瓦片索引计算

注意用Math.floor做索引取整,不要用Math.round,避免半格位置跳变导致识别偏移:

// 输入canvas内鼠标坐标,返回悬停的瓦片[列索引, 行索引]
function getHoverTile(mouseX, mouseY) {
  const [cartX, cartY] = isoToCar(mouseX, mouseY);
  // 超出网格范围时返回的索引会<0或>=网格行列数,可自行做边界过滤
  const col = Math.floor(cartX / tileSize);
  const row = Math.floor(cartY / tileSize);
  return [col, row];
}

注意事项

  • 该方案完全保留你原有√3系数的投影逻辑,和30度制作的美术资源不会出现对齐偏差
  • 如果需要做边缘容错(比如鼠标在瓦片交界位置时避免频繁跳变),可以在计算索引前给cartX/cartY加固定偏移,偏移值根据美术资源的实际碰撞区域调整即可
  • 验证方法:将任意carToIso(x,y)的输出传入isoToCar,得到的结果和原始输入(x,y)的误差仅来自JS浮点数计算,可忽略

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 12:15:28