Liquid 液态流体
双层液态特效群组:SVG 剪影层承载 goo 融合与真实阴影,内容层保持清晰可交互。
Liquid 液态流体
基础用法
Morph(默认):给条目 x / y,元素与液面在同一 JS 时钟里同步动画,相触的块自动像水滴一样桥接、融合。
示例加载中...
Move 拖尾
Move:由你自己移动元素(CSS、指针事件都可以),液面在弹簧上追赶它,并拖出小水滴尾巴。
示例加载中...
组合示例
形变物理
morph.shape 打开液态形变:质心先流向新位置,尺寸与圆角随后跟上;内容在运动中交叉模糊、落定时变清晰。
<template>
<TxLiquid :blur="8" fill="var(--tx-bg-color)">
<TxLiquidItem :morph="{ shape: true, speed: 1, bounce: 0.5 }">
<div :class="open ? 'panel-open' : 'panel-closed'">…</div>
</TxLiquidItem>
</TxLiquid>
</template>
溶解
dissolve 是与 effect 正交的修饰:接触点处条目的图像被湍流位移场熔进邻居,是两种液体的混合而不是模糊。文本永远不会被熔化。
<template>
<TxLiquid :blur="10" fill="var(--tx-bg-color)">
<TxLiquidItem dissolve>
<img class="avatar" src="/a.png" alt="">
</TxLiquidItem>
<TxLiquidItem :dissolve="{ mix: 0.7, active: dragging }">
<img class="avatar" src="/b.png" alt="">
</TxLiquidItem>
</TxLiquid>
</template>
交互契约
TxLiquid渲染position: relative; isolation: isolate容器;剪影 SVG 以z-index: -1垫在所有子元素之下,熔化叠层渲染在内容层之上,两者均pointer-events: none。TxLiquidItem必须处于TxLiquid内,否则抛错。- 群组尺寸需要容纳条目的完整行程(如菜单展开后的占位);桥接近似发生在
blur ≳ 间距时,该融合的块显得分离时先调大blur。 - 圆角从计算样式测量,百分比、胶囊、圆形均可;
radius可覆盖。 x/y/scale驱动的条目由组件写transform,消费方不要再对包装器写 transform 或 filter。morph.shape运动期间会对内容写filter: blur();dissolve会对<img>写mask-image,不要与自己的同名样式组合。dissolve与effect="move"组合会被忽略并给出警告;prefers-reduced-motion: reduce下组件驱动的过渡塌缩为瞬移。
API
TxLiquid Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
blur | number | 6 | goo 模糊 σ(px),决定多远开始桥接。 |
contrast | number | 18 | 透明度对比斜率,越大液面边缘越锐。 |
fill | string | '#fff' | 液面颜色,支持 var() 主题化。 |
shadow | string | - | box-shadow 语法,渲染在融合后的剪影上;inset 层画在液面内侧。 |
filterPadding | number | 24 | 滤镜区域额外余量(px),供 blob 溢出群组时使用。 |
TxLiquidItem Props
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
effect | 'morph' | 'move' | 'morph' | 液态行为。 |
morph | MorphTuning | - | shape / speed / bounce / contentBlur 与 advanced 逃生口。 |
move | MoveTuning | - | springiness / wobble / stretch / trail 与 advanced。 |
dissolve | boolean | number | DissolveOptions | - | 接触熔化修饰,0..1 缩放强度。 |
x / y / scale | number | 0 / 0 / 1 | 组件驱动位移;与液面像素级同步。 |
transition | 'snappy' | 'smooth' | 'bouncy' | SpringConfig | { duration, ease } | 'smooth' | x/y 的弹簧或时长过渡。 |
delay | number | 0 | 过渡延迟(ms),做交错入场。 |
observe | boolean | false | 由你的代码动画时让液面跟随渲染矩形;morph.shape、dissolve、move 隐含开启。 |
radius | number | [tl, tr, br, bl] | 测量值 | 覆盖液面圆角。 |
Slots
| 插槽名 | Props | 说明 |
|---|---|---|
default(TxLiquid) | - | 群组内容,通常是若干 TxLiquidItem。 |
default(TxLiquidItem) | - | 真实交互内容;背景应保持透明,液面即表面。 |
Events
不发出公开事件。
Exposed Methods
不暴露公开实例方法。
CSS Variables
不消费公开 CSS 变量;fill 可传 var(--surface) 实现明暗主题。
最佳实践
- 条目背景保持透明——blob 才是表面;不透明内容(如圆形照片)恰好盖住自己的液面,只在桥接处露出液体。
fill传 CSS 变量(如var(--tx-bg-color)),让液面随明暗主题切换。- 阴影写在
shadow上而不是子元素上,才能让一份阴影贴着融合后的液面走过每次分合。 - 该融合不融合优先调
blur与间距的比例,再怀疑其他参数。 - 高频拖拽场景优先
effect="move"的默认参数;advanced只在确认默认手感不满足时使用。
审阅说明
- 已人工核对
packages/tuffex/packages/components/src/liquid/下index.ts、TxLiquid.vue、TxLiquidItem.vue、types.ts与liquid.test.ts。 - 物理引擎
observer.ts、spring.ts、geometry.ts、shadow.ts逐字移植自上游liquid-gooey(MIT © Jakub Antalik),仅做 strict-TS 索引加固;滤镜链在filter-primitives.ts改为命令式构建以规避 SVG 命名空间歧义。 - 上游 React 的
Liquid/Liquid.Item对应此处TxLiquid/TxLiquidItem;className/style由 Vue 属性透传承担。
Source
- Component source:
packages/tuffex/packages/components/src/liquid/src/TxLiquid.vue、TxLiquidItem.vue。 - Types:
packages/tuffex/packages/components/src/liquid/src/types.ts。 - Upstream: Jakubantalik/Libraries · liquid-gooey(MIT)。
- 实测覆盖: Coverage:
packages/tuffex/packages/components/src/liquid/__tests__/liquid.test.ts验证剪影/熔化双层渲染、goo 滤镜链构建、阴影拆分(drop-shadow 与 SVG 通道)、morph blob 镜像、observed 注册与群组外抛错。
查看源码
packages/tuffex/packages/components/src/liquid/index.ts