【免费下载链接】liquid_glass_widgets
Flutter UI kit implementing Apple's iOS 26 Liquid Glass design language - a comprehensive glass widget library with real shader-based blur, physics-driven jelly animations, and dynamic lighting. Works on every platform out of the box.
点按按钮,一块"玻璃水珠"从按钮里拉伸出来,滴落到菜单位置,最后稳稳落定——这就是 iOS 26 的液态玻璃(Liquid Glass)效果。开源项目Liquid Glass Widgets把这一整套视觉语言带进了 Flutter,而它的灵魂就是液态变形引擎(Liquid Morph Engine):一个用物理弹簧驱动时间、用Metaball SDF 着色器画形状的动画系统,逐帧计算出两个"液滴"如何运动、拉伸、融合。本文用通俗的方式讲透这套引擎的原理,几乎不需要读代码。
什么是液态变形引擎?一个菜单,两颗"液滴"
官方把整个动画拆成了两个概念上的"Blob"(液滴),这是理解一切的钥匙:
| 液滴 | 角色 | 行为 |
|---|---|---|
| Blob A(锚点) | 触发按钮的"幽灵替身" | 停留在原位,在动画前 40% 逐渐缩小消失 |
| Blob B(主体) | 正在变形的菜单容器 | 从按钮中心飞向菜单中心,同时从小变大 |
关键洞察是:两颗液滴之间的"泪滴状颈部"没有任何手工绘制的几何,它完全由 Metaball 着色器自动"长"出来。引擎唯一要做的事,就是回答每一帧的问题:
Blob B 现在应该在哪?多大?和 Blob A 融合到什么程度?
答案由 LiquidMorphState 这个"每帧一份"的值对象给出,里面的pathT(位置)、sizeT(尺寸)、anchorScale(锚点缩放)、blend(融合强度)都是引擎预先算好的,UI 层拿来直接用即可。
第一套原理:为什么是"欠阻尼"物理弹簧? 🏀
菜单打开/关闭的时机不是靠"定时 300 毫秒",而是靠真实的弹簧模拟。在 liquid_morph_physics.dart 里,开合动画用的是同一族欠阻尼弹簧:
质量 mass: 1.0 刚度 stiffness: 120.0 → 固有频率 ω₀ ≈ 11 rad/s 阻尼 damping: 16.0 → 阻尼比 ζ ≈ 0.73阻尼比ζ < 1(欠阻尼)是刻意为之——弹簧会冲过头再弹回来。正是这一次"冲过头",制造了 iOS 26 那个标志性的橡皮筋回弹手感:
- 打开时:弹簧冲向 1.0 的过程中配合 J 曲线过冲,液滴像被一根橡皮筋"弹射"出去,颈部被拉到最长;
- 关闭时:弹簧会冲过 0.0 变成负值,液滴"砸"回按钮位置,触发按钮还会跟着轻轻一震(push 动量),就像真的被液体撞了一下。
关闭时还会注入一个初始速度提示(closeVelocityHint = -3.2),相当于"松手时猛地把菜单往外一拽",让回弹幅度更饱满。
📌新手提示:这套物理常量是互相咬合的,所以引擎不开放自定义弹簧参数,只给出四档语义化速度(MorphSpeed:slow / normal / fast / instant),任何一档都自动保持 ζ ≈ 0.73 的欠阻尼比例——保证"有回弹"这一灵魂不变,只是快慢不同。
第二套原理:Metaball 如何"画出"泪滴颈部 💧
光有弹簧只能算出位置,"液体"的观感来自 GPU 上的SDF(有向距离场)+ Metaball 融合。核心逻辑在 shaders/sdf.glsl 的smoothUnion函数:
- 每个玻璃形状(按钮、菜单)都用 SDF 描述成一个"距离场"——画面中每个像素只知道"我离这个形状有多远";
- 两个形状的距离值不做简单取小(那样是硬边并集),而是用
smoothUnion(d1, d2, k)做平滑并集——两个形状靠近时,边缘会像两滴水接触时一样鼓起、融合; - 引擎输出的
blend值(0–28 的模糊单位)就控制这个融合的"张力":两滴完全重叠时 blend = 0(互不相扰),泪滴颈部拉到最开时 blend 最大(颈部最粗)。
所以整条"液体颈部"是算出来的光学错觉,没有一条贝塞尔曲线参与。这也解释了为什么效果在不同尺寸、不同距离下都自然——融合强度跟着两滴的分离度自动伸缩。
上图这类背景图正是玻璃"折射"的对象:最终成像由 shaders/liquid_glass_render.frag 的渲染管线完成,包含折射、色散、边缘高光等多重效果。
一次完整变形:五个阶段的"液体生命周期" 🌊
引擎把动画切成五个语义阶段(MorphPhase),你无需自己从原始数值反推"现在演到哪了":
打开方向:idle → detaching → travelling → arriving → settled 关闭方向:settled → arriving → travelling → detaching → [回弹] → idle| 阶段 | 弹簧值区间 | 你在屏幕上看到什么 |
|---|---|---|
idle | < 0.001 | 静止,动画结束 |
detaching | 0 – 0.4 | 幽灵按钮(Blob A)缩小,液滴开始"剥离" |
travelling | 0.4 – 0.8 | 泪滴颈部拉伸到最长,最"液体"的时刻 |
arriving | 0.8 – 1.0 | 液滴逼近目标,颈部开始回缩 |
settled | ≥ 1.0 | 菜单完全落定 |
关闭时还有一个精巧的hasHandedOff交接闩锁:弹簧冲过 0 的瞬间,引擎把"幽灵替身"换回"真按钮"。用户在回弹过程中看到的始终是幽灵在承接撞击,而真按钮重新出现时已经静止归位——肉眼完全察觉不到这次"换人"。
自适应阻尼:菜单越大,流动越"克制"
小按钮变弹出菜单还好,那如果变形目标是半屏模态面板呢?距离远、尺寸差大,如果还用同一套曲线,液滴会"下坠" 35–40 像素,非常出戏。
引擎的解法是自适应模式(尺寸比scaleDelta > 1.5时自动启用):
- J 曲线过冲幅度按距离反比衰减:物理过冲被约束在 10–14 像素以内,颈部仍然可见的"拉丝",但不再有夸张的下坠;
- 尺寸曲线切换为 smootherstep:大变形早期液滴保持紧凑,落点附近才快速"绽放";
- blend 融合度按尺寸比衰减(下限 0.2):防止 SDF 把半个屏幕都糊成一体;
- 回弹推击设上限:触发按钮的震动始终是一下"轻点",而不是像素级的猛撞。
这些细节都在 LiquidMorphPhysics.compute 中实现,是"小菜单灵动、大菜单稳重"的秘密。
怎么亲手体验液态变形? 🔭
不需要写任何代码,项目示例里已经内置了两个"参考实现":
GlassMenu/GlassMenuItem:触发按钮 → 悬浮菜单的液态变形,是引擎的教科书级集成,源码见 glass_menu_internal.dart;GlassModalSheet.show(morphFrom:):触发按钮 → 模态面板的变形,比菜单更进一步——它要解决"变形液滴"与"真正的路由页面"的无缝交接(面板在整个变形期间始终挂载在下方,最后才"揭示"出来),源码见 glass_modal_sheet_morph.dart。
想给自己的组件接入,只需三步:
- 在
State里创建 GlassMorphController(记得dispose); - 每帧调用
computeState(finalDx:, finalDy:)拿到渲染状态; - 按状态摆放两个 Blob、把
state.blend传给玻璃层的融合参数。
完整的集成指南、MorphSpeed参数表与最小示例都在 docs/LIQUID_MORPH_ENGINE.md。
无障碍:Reduce Motion 用户看到什么 ♿
引擎自动读取系统的Reduce Motion / Remove Animations设置。开启后,弹簧直接切换为instant档位——菜单"一步到位"出现与消失,没有泪滴颈部、没有回弹。GlassMenu在didChangeDependencies()中自动接线,自定义组件也只需一行setDisableAnimations()即可跟上,用户运行中切换设置也能实时生效。
小结
Liquid Glass Widgets 的液态变形引擎,本质上是两套物理直觉的合谋:
- 弹簧动力学(ζ ≈ 0.73 欠阻尼 + J 曲线过冲)负责"时间"——什么时候到哪、冲过头多少、回弹多猛;
- SDF Metaball 平滑并集负责"空间"——两颗液滴之间那个会拉伸、会断裂、会融合的颈部。
一帧接一帧,这两套系统各自独立又严丝合缝地咬合,才让菜单真正"流动"起来,而不是"缩放"或"滑动"。这正是 iOS 26 液态玻璃手感在跨平台 Flutter 应用里的完整复刻——打开、飞行、落定、回弹,每一毫秒都有物理解释。
【免费下载链接】liquid_glass_widgets
Flutter UI kit implementing Apple's iOS 26 Liquid Glass design language - a comprehensive glass widget library with real shader-based blur, physics-driven jelly animations, and dynamic lighting. Works on every platform out of the box.
相关推荐
GlassModalSheet 完全指南:Liquid Glass Widgets 模态弹层的参数、手势与液态变形细节
GlassModalSheet 完全指南:Liquid Glass Widgets 模态弹层的参数、手势与液态变形细节 liquid_glass_widgets
让Liquid Glass活起来:liquid-glass-studio超椭圆形状、弹簧动画与Blob融合详解
让Liquid Glass活起来:liquid glass studio超椭圆形状、弹簧动画与Blob融合详解 liquid glass studio 是一款在
Liquid Glass Widgets 实战:用 GlassScaffold 5 分钟搭建第一个液态玻璃界面
Liquid Glass Widgets 实战:用 GlassScaffold 5 分钟搭建第一个液态玻璃界面 想在自己的 Flutter 应用里复刻 iOS
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考