Canvas绘制等距视角图形:轴测投影的坐标转换

Canvas通过轴测投影(如等轴测)实现3D效果,核心是将(x,y,z)经线性变换映射为像素坐标,保持平行性;可用setTransform定义坐标系、按z排序处理遮挡、逆变换支持鼠标交互。

canvas绘制等距视角图形:轴测投影的坐标转换

Canvas本身不直接支持3D,但通过轴测投影(尤其是等轴测)能把三维结构画得有立体感,关键在于把(x, y, z)正确映射到画布的(x, y)像素位置。这不是简单缩放,而是按固定角度做线性变换——所有平行线保持平行,没有透视衰减,适合建筑示意、游戏地图或数据可视化。

理解等轴测的核心坐标公式

等轴测投影中,x、y、z三轴在画布上互成120°,常用简化实现是让x轴向右下30°、y轴向左下30°、z轴垂直向上。对应转换公式为:

  • canvasX = x × cos(30°) − y × cos(30°) = (x − y) × √3/2
  • canvasY = z − (x × sin(30°) + y × sin(30°)) = z − (x + y)/2

实际编码中常进一步简化为整数比例,例如Isomer使用的近似:canvasX = x − y,canvasY = (x + y) / 2 − z。注意:最终y值需再翻转适配Canvas原点在左上角——即绘制前用drawY = height − canvasY

用setTransform实现可复用的轴测坐标系

手动计算每个点太繁琐。更干净的做法是用ctx.setTransform()一次性定义整个轴测空间:

  • 先调用ctx.save()保存原始状态
  • ctx.translate(originX, originY)把逻辑原点(比如场景中心)移到画布合适位置
  • 再用ctx.transform(a, b, c, d, e, f)传入轴测变换矩阵,例如:
    a = cos(30°), b = sin(30°), c = −cos(30°), d = sin(30°), e = 0, f = 0
    这样后续所有fillRectlineTo都自动按轴测规则绘制
  • 结束时ctx.restore()恢复默认坐标系,不影响其他绘制

处理z轴深度与遮挡关系

轴测图没有自动深度排序,必须人工控制绘制顺序:

  • 按z坐标从远到近排序所有图形元素(z值越小越靠后)
  • 对立方体等组合图形,拆解为面(front、top、right),分别计算各面顶点并按z均值排序
  • 避免用globalAlpha模拟半透明遮挡——它会破坏轴测清晰度;优先用纯色分层绘制

鼠标交互与坐标反推

用户点击画布时,要还原出对应的(x, y, z)逻辑坐标:

  • 先用getBoundingClientRect()获取canvas真实视口位置,换算出相对于canvas左上角的像素坐标
  • 逆用正向变换公式:已知canvasX、canvasY,解二元一次方程组求x和y(z通常由层级或高度预设)
  • 例如从简化公式px = x − ypy = (x + y)/2 − z出发,可得:
    x = (2×py + 2×z + px) / 3,y = x − px

不复杂但容易忽略

文章来自机圈观察员网,发布者:,转载请注明出处:https://www.jqgcy.com/xinjizixun/127151.html

如何比较Sass与Less在处理复杂CSS变量时的性能?
上一篇 2026-07-20 06:39
如何在Go语言中进行语言学习并掌握Go语言中原子引用的用法
下一篇 2026-07-20 06:39

相关推荐