Canvas通过数学投影将三维坐标转换为二维实现3D效果,关键在于精准计算、深度排序和光照模拟;使用单位立方体顶点、欧拉角旋转、透视投影公式、z值排序面片及法向量光照计算,并用requestAnimationFrame实现流畅动画。

Canvas 本身是 2D 绘图 API,不能直接渲染 3D,但可以通过数学投影把三维坐标“压平”到二维画布上,再配合旋转、深度排序和光照计算,实现视觉上真实的 3D 立方体透视效果。关键不在“画立体”,而在“算得准、排得对、画得顺”。
定义立方体的三维顶点坐标
用中心在原点的单位立方体最方便:8 个顶点坐标范围在 ±0.5(或 ±1),例如[[-0.5,-0.5,-0.5], [0.5,-0.5,-0.5], [0.5,0.5,-0.5], ...]
每个点含 x/y/z,后续所有变换都基于这组原始三维数据。
对顶点做三维空间变换
- 先绕 x、y、z 轴依次旋转(推荐用欧拉角,或更稳定的四元数)
- 再做平移(比如整体移动到画布中央)
- 所有运算必须在投影前完成,否则 z 坐标失真会影响透视和光照
旋转后仍保持三维坐标,这是后续投影和光照的基础。
用户要生成可打印的中文字帖/练习纸、导出多页 A4 PDF 报告,或把 SVG 设计稿零误差还原到 Canvas 时使用。本技能是「Canvas 内容工厂闭环」的总控,编排:网格渲染引擎(13 种教育网格+拼音标注) → 多页 PDF 导出(A4 合成) → SVG 精准复刻(坐标误差<0.001px)。触发词:生成字帖、练习纸、导出 PDF、SVG 转 Canvas、印刷级还原、A4 报告、米字格田字格。
应用透视投影公式转为 2D 坐标
不用 WebGL,就手动套公式:
- 设观察距离
d(如 5),越大透视越弱,越接近正交 - 对每个点
(x, y, z),投影后为:x' = x / (d − z)y' = y / (d − z) - 注意:z 必须小于 d,否则分母为负或零,会导致翻转或崩溃;可加安全判断,如
z = Math.min(z, d - 0.1)
按深度排序面片再绘制
Canvas 没有 Z-buffer,必须手动控制遮挡:
- 每个面由 4 个顶点组成,取它们投影前的平均 z 值(不是投影后的!)作为深度参考
- 将 6 个面按平均 z 从大到小排序(z 越大越靠近观察者)
- 逆序绘制:先画 z 最大的面(最近),再盖上稍远的——实际是“远的先画,近的后画”,避免覆盖错误
添加基础光影增强立体感
- 对每个面,用两个边向量叉乘算出单位法向量
n - 设定光源方向(如
[0, -1, -1]),归一化后与n点积,得漫反射强度diffuse = max(0, n·light) - 加环境光(如
0.2 + 0.8 * diffuse)防止背面全黑 - 填充颜色时,用该强度缩放 RGB 分量,比如
rgb(120*l, 180*l, 255*l)
用 requestAnimationFrame 实现流畅旋转
- 不要用 setInterval,每帧调用
requestAnimationFrame - 微调旋转角度(如
angleY += 0.01),结合时间差 delta 可实现帧率无关的匀速转动 - 开启
ctx.imageSmoothingEnabled = false避免缩放模糊(尤其像素风或清晰线框需求)
不复杂但容易忽略:光照和深度排序必须基于原始三维坐标,投影只是最后一步显示转换。

















