组件/Liquid 液态流体

Liquid 液态流体

双层液态特效群组:SVG 剪影层承载 goo 融合与真实阴影,内容层保持清晰可交互。

Verified自 0.3.9

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,不要与自己的同名样式组合。
  • dissolveeffect="move" 组合会被忽略并给出警告;prefers-reduced-motion: reduce 下组件驱动的过渡塌缩为瞬移。

API

TxLiquid Props

属性名类型默认值说明
blurnumber6goo 模糊 σ(px),决定多远开始桥接。
contrastnumber18透明度对比斜率,越大液面边缘越锐。
fillstring'#fff'液面颜色,支持 var() 主题化。
shadowstring-box-shadow 语法,渲染在融合后的剪影上;inset 层画在液面内侧。
filterPaddingnumber24滤镜区域额外余量(px),供 blob 溢出群组时使用。

TxLiquidItem Props

属性名类型默认值说明
effect'morph' | 'move''morph'液态行为。
morphMorphTuning-shape / speed / bounce / contentBluradvanced 逃生口。
moveMoveTuning-springiness / wobble / stretch / trailadvanced
dissolveboolean | number | DissolveOptions-接触熔化修饰,0..1 缩放强度。
x / y / scalenumber0 / 0 / 1组件驱动位移;与液面像素级同步。
transition'snappy' | 'smooth' | 'bouncy' | SpringConfig | { duration, ease }'smooth'x/y 的弹簧或时长过渡。
delaynumber0过渡延迟(ms),做交错入场。
observebooleanfalse由你的代码动画时让液面跟随渲染矩形;morph.shapedissolvemove 隐含开启。
radiusnumber | [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.tsTxLiquid.vueTxLiquidItem.vuetypes.tsliquid.test.ts
  • 物理引擎 observer.tsspring.tsgeometry.tsshadow.ts 逐字移植自上游 liquid-gooey(MIT © Jakub Antalik),仅做 strict-TS 索引加固;滤镜链在 filter-primitives.ts 改为命令式构建以规避 SVG 命名空间歧义。
  • 上游 React 的 Liquid / Liquid.Item 对应此处 TxLiquid / TxLiquidItemclassName / style 由 Vue 属性透传承担。

Source

  • Component source: packages/tuffex/packages/components/src/liquid/src/TxLiquid.vueTxLiquidItem.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