跳到主要内容
CHANGELOG · 2026-09-28

🐛 骰子模拟器:修掉每次投掷都闪一下的矩形色块

骰子模拟器(文档)改真 3D 之后,有个渲染问题被用户报了上来:投掷过程中骰子周围会闪出一块硬边矩形——有时是米白色,有时是半透明深色块,位置和大小都不固定,一瞬即逝但几乎每次都有。

🐛 两处合成层脆弱写法​

伪影来自 CSS 3D 的两个已知脆弱点,都不是逻辑错误,而是交给合成器的方式不对:

① 给透视根加非等比缩放​

抛掷动画原本在 .die-body 上做「压扁回弹」,关键帧是 scale(1.12, 0.86) 这种 x≠y 的缩放。问题在于 .die-body 同时是整个 preserve-3d 子树的 perspective 根:透视根上的非等比缩放会让 3D 子树进入合成器的非线性变换(NLTH)路径——3D 内容被栅格化进一张带裁剪的纹理,裁剪矩形一旦算错,就会闪出一块硬边矩形。

平移是仿射变换,走的是合成器快路径,不会产生这种伪影。所以改成:

  • .die-body 只做纯位移(抛物线 + 三次回弹保留)
  • 落地冲击感改由 .die-shadow 承担——它是纯 2D 元素,不在 3D 路径上;落地瞬间阴影放大到 1.3 倍并加深,读起来更实

② 每个面的背面剔除​

backface-visibility: hidden 会给 6 个面各强制一个独立渲染面并做剔除,动画中渲染面的裁剪偶尔算错,同样是这个色块。

而它本来就是多余的:面已经是直角(border-radius 早就为了接缝去掉了),6 个面严丝合缝;立方体是凸体,背面投影必然被放大的正面完全覆盖。所以直接去掉,骰子依然是实心的。

上一版文档里写的「直角面 + 背面剔除才能拼出实心骰子」,这个说法不准确——背面剔除从来不是必需条件,正面本来就够。这条已一并更正。

⚠️ 一个诚实的说明​

这个伪影没能在我这边的环境里复现:无头 Chrome 单次会话内高频抓了 45 帧、内置浏览器约 10 帧,深色/浅色主题都试过,最长连续色块都在 60–123px(正常骰面宽度),没有出现 200–400px 的矩形。合成器行为和用户实际浏览器不同。

所以这次是按机制消除脆弱写法,不是"改完看着好了"。上线后需要用户实际确认一下——如果还有残留,下一步就是录屏逐帧定位。

✅ 顺带补上的验证​

改完之后重新确认了正确性,没有只看渲染:

  • 测试 12/12 通过
  • 骰面仍实心(去掉背面剔除后无背面透出、无接缝)
  • 落定姿态仍正确:顶面点数 = 掷出的点数(实测 3 + 1 = 4、2 + 1 = 3,顶面读数与结果区一致)
  • D4 的空白面、多颗错峰抛起、空格键、点击单颗重掷均未受影响