Skip to content

githup v1.2.11(液态玻璃:背景真的会弯)

Choose a tag to compare

@Buwrt Buwrt released this 26 Sep 12:28
· 519 commits to main since this release

githup v1.2.11(液态玻璃:背景真的会弯)

这一版没有任何新功能,只换了一件事:玻璃的材质。

以前的顶栏、底栏、弹层、卡片是毛玻璃——背景先糊掉(blur 20~30px)再透上来。
柔和是柔和,但有个硬伤:背景内容本身不弯折。水下的东西平着过去,再怎么看都不是水。

液态玻璃(liquid-glass)走另一条路:用内联 SVG 位移滤镜把背景扭过来,
玻璃给用户看的不只是「透」,而是「折射」。

版本号只动第三位(1.2.10 → 1.2.11),按 README 的规矩属于可选更新:
装了 v1.2.10 的会收到提示,不更也能继续用。


一、为什么必须整套换

一句话的物理约束:

模糊是折射的天敌。blur 超过 6px,形变就糊得看不见了。

原来的顶栏是 blur(20px)、底栏 blur(26px)。直接把位移滤镜叠上去不会有任何视觉效果,
水面当场死掉。所以这不是「加个效果」,是整套材质取值倒过来:

以前(毛玻璃) 现在(液态)
模糊量 20~30px 3px(必须 ≤ 4px)
面罩透明度 .62 .30
噪点 .22(毛玻璃的灵魂) .06(液态的敌人)

噪点从 .22 压到 .06 是关键:水面看着是水,全靠背后那块扭曲的图案看得清,
铺一层颗粒上去等于给它蒙雾——GPU 每帧照旧算位移,肉眼什么都看不见。
留 .06 只是防止大面积渐变出现色带。

二、一个差点让整件事白做的前提

原来的背景是全不透明的。

.card { background: var(--bg); }        /* #ffffff 实色 */
.list { background: var(--bg); }
/* 画布 --canvas 也是实色 */

实色透实色——不管挂什么滤镜,输入都是同一块颜色,把纯色扭多少像素它还是纯色。

所以先给画布铺了一层能被折射的内容:

  • 三团很淡的径向色晕——提供大块明暗变化
  • 一层极淡的斜纹——这是关键。折射看不看得出来取决于背后有没有高频图案,
    光是平滑渐变,扭了也看不出来
  • background-attachment: fixed——让背景不跟着滚,卡片从它上面滚过去时图案相对移动,
    才有「内容从水面下流过」的观感

深色模式配了另一组更冷的色晕。

三、覆盖范围,以及两处刻意的例外

顶栏、底栏胶囊、弹层、提示条、列表卡片统一到同一套语言。

其中两处故意不一样:

元素 为什么降力度
弹层(.sheet) 它是要静下来读的东西,底下全是扭动会累。折射力度减半、面罩加厚,再补一层 brightness(1.18) 抵消遮罩的压暗
列表卡片 惯性滚动时每帧都要为每张卡片重算位移贴图,若干张同屏就是「每帧 × 张数」——这是实打实的掉帧,不是理论顾虑

另外两处小改:

  • 面罩变薄、噪点去掉之后,撑住玻璃形状的就只剩边缘那两道 inset(上缘受光、下缘背光),这次把它加重了。
  • 按压动效换成弹簧曲线 .34,1.56,.64,1(末段 >1 会冲过头再收回)。列表行不加:
    它在 overflow:hidden 的卡片里,缩放会被裁出白边,一行缩放还会顶着相邻行,整列看着在抖。

四、踩到的两个 CSS 陷阱

陷阱一:含 url() 的折射行不能包进 var()。

把 saturate(...) blur(...) 抽成变量省几行——不行。自定义属性一旦替换出的值无效,
该声明就是 invalid at computed-value time,属性会掉回 inherit/initial,
不会回落到同属性的前一条声明。老 WebView 会直接得到一个「没有 backdrop-filter」的顶栏,
而不是兜底。字面写的话,不认的引擎当作解析失败整条丢掉,兜底自然留下。

于是每个元素写成四行:

backdrop-filter: saturate(...) blur(20px);            /* 兜底 */
-webkit-backdrop-filter: saturate(...) blur(20px);    /* 兜底(老 WebView 只认前缀) */
backdrop-filter: url(#lens) saturate(...) blur(3px);  /* 真折射 */
-webkit-backdrop-filter: url(#lens) saturate(...) blur(3px);

陷阱二:<defs> 不能用 display:none 藏。 被隐藏的元素不进渲染树,
引用它的滤镜会整条失效,玻璃会悄悄退化成「一层几乎不糊的半透明面」——
所以改用 0 尺寸 + 绝对定位躲起来。

五、性能(这句是真话)

液态玻璃是三档玻璃里最贵的一档:backdrop-filter 要逐帧重算它覆盖的那块背景,
位移滤镜更贵。已经做了两处降级(列表走 soft 档、朴素样式的隔离完好),
但中低端机型上滚动变卡是有可能的。

真觉得卡:设置里关掉「iOS 风格」,立刻回到从前的实体栏 + 纯色背景。
这个开关这次一行没动,是改动的第一约束。


附:改动清单

文件 变化
app/src/main/assets/web/index.html +26 行:内联两片位移滤镜 #lens / #lens-soft
app/src/main/assets/web/css/app.css +173 行:材质取值、背景层、折射回落、弹簧曲线

Java / Kotlin 一行未动。 全部改动隔离在 html[data-nav="glass"] 这条轴上,
朴素样式完全不受影响(有脚本逐条校验)。