🐛 骰子模拟器:修掉每次投掷都闪一下的矩形色块
骰子模拟器(文档)改真 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 的空白面、多颗错峰抛起、空格键、点击单颗重掷均未受影响