A WebGL visual component library based on Vue 3 + Three.js + GSAP, containing two card families:
- LightningCard: rounded cards with a liquid glass texture, each containing a procedural lightning bolt that wanders randomly left and right within the card and periodically "strikes" — flashing, morphing, and fading. Comes with 1 hero card + 24 named theme cards, each with its own color scheme and lightning shape.
- LiquidMixingCard: rounded capsule cards with domain-warped FBM color clouds that slowly "breathe", driven by hover / mouse-stir interaction. Comes with 1 main card + 24 named theme cards.
基于 Vue 3 + Three.js + GSAP 的 WebGL 视觉组件库,包含两个卡片家族:
- LightningCard:液态玻璃质感的圆角卡片,内置一颗程序化闪电,闪电在卡片内部左右随机往返游走,并周期性地"闪击"——闪光、换形、衰减。内置 1 张主图 + 24 套命名主题,每套主题拥有独立配色与闪电形态。
- LiquidMixingCard:流体混合胶囊卡片,域扭曲 FBM 色彩云雾缓慢"呼吸",支持悬停与鼠标搅动交互。内置 1 张主卡 + 24 套命名主题。
- GLSL Lightning Engine: Procedurally generates lightning trunks and branches with dual-seed shape blending — each strike smoothly morphs into a brand-new random shape.
- GLSL 闪电引擎:程序化生成闪电主干与分支,双种子形态混合,每次闪击平滑变形为全新随机形状
- Liquid Mixing Clouds: Two layers of 5-octave fractal noise push each other (domain warping), interpolating between 3 theme colors — watercolor clouds that never repeat.
- 流体混合云雾:两层 5 阶分形噪声互相推挤(域扭曲),在 3 个主题色间平滑插值,水彩云雾永不重复
- Liquid Glass Texture: Deep background with subtle borders, white-core colored glow, Fresnel outlines, and specular highlights — all composited in real time within the fragment shader.
- 液态玻璃质感:深底细边、白芯彩色光晕、菲涅尔描边与高光,全部在片元着色器中实时合成
- Dynamic Motion Trail: Lightning drift velocity is per-frame low-pass filtered and integrated into a flowing phase, producing directional motion trails (prevents frame-difference noise from being amplified by global time).
- 动态拖尾:闪电游走速度经逐帧低通滤波后积分成流动相位,产生方向感拖尾(避免帧差噪声被全局时间放大)
- GSAP Animation Orchestration: Four independent animation layers — entrance reveal, left-right drift, filament flicker, and strike flash — with centralized parameter configuration.
- GSAP 动画调度:入场揭示、左右游走、灯丝明暗闪烁、闪击闪光四层动画独立调度,参数集中配置
- Shared Renderer: All card instances share a single WebGL context (scissor/viewport region-based rendering + copy to each card's 2D canvas) — dozens of cards on screen with no performance issues, avoiding browser WebGL context limits.
- 共享渲染器:全部卡片实例共用 1 个 WebGL 上下文(scissor/viewport 分区域渲染 + 拷贝到各卡片 2D canvas),数十张卡片同屏无压力,规避浏览器 WebGL 上下文数量上限
- Rounded Corners: Corner radius is a ratio of the card height (shader SDF + CSS clipping double-layered), overridable per instance via the
cornerRadiusprop. - 圆角:圆角为卡片高度的比例(shader SDF + CSS 裁剪双层实现),可用
cornerRadius属性按实例覆盖 - Responsive: Card dimensions and font sizes all use
clamp()fluid layout, adapting to any screen size. - 响应式:卡片宽高、字号全部使用 clamp() 流式布局,自适应任意屏幕
npm install
npm run dev # Development server / 开发服务器
npm run build # Production build (outputs to dist/) / 生产构建(输出到 dist/)
npm run preview # Preview production build / 预览生产构建Both components read their config from a config hub by the name prop. They share the same props, overlay modes, and rendering infrastructure.
两个组件均通过 name 属性从配置中心取卡,props、覆盖层模式与渲染基建完全一致。
<LightningCard name="LIQUID SURGE" /> <!-- Hero card (liquid-lightning algorithm) / 主图(liquid-lightning 算法)-->
<LightningCard name="Current Pulse" /> <!-- A theme card (liquid-style algorithm) / 某张主题卡(liquid-style 算法)-->
<LightningCard name="Current Pulse" index="01" /> <!-- Theme card + top-left index / 主题卡 + 左上角序号 -->
<LightningCard name="Current Pulse" fluid /> <!-- Fluid width (fills parent, grid layout) / 宽度占满父容器(网格布局)-->
<LightningCard name="Current Pulse" width="480px" height="300px" />
<!-- Custom width/height (passing one is enough) / 自定义宽高(传其一即可)-->
<LightningCard name="Blood Echo" :progress="88" /> <!-- Travel percent: bolt positioned at 88% of card width, smooth transition on update / 游走百分比:闪电定位在 88% 处,更新时平滑过渡 --><LiquidMixingCard name="LIQUIDFLOW" /> <!-- Main card (content overlay) / 主卡(内容覆盖层)-->
<LiquidMixingCard name="Sunset" /> <!-- A theme card (name label) / 某张主题卡(名称 label)-->
<LiquidMixingCard name="Sunset" index="01" /> <!-- Theme card + top-left index / 主题卡 + 左上角序号 -->
<LiquidMixingCard name="Aurora" :progress="88" /> <!-- Flow strength target 0–100 / 流动强度目标 0~100 -->| Property / 属性 | Type / 类型 | Default / 默认 | Description / 说明 |
|---|---|---|---|
name |
String |
Required / 必填 | Card English name, key in LIGHTNING_CARDS / LIQUID_MIXING_CARDS (e.g. Current Pulse / Sunset) / 卡片英文名称,配置中心的 key(如 Current Pulse / Sunset) |
showContent |
Boolean |
true |
Whether to show the text overlay / 是否展示文案覆盖层 |
index |
Number/String |
null |
Theme card index (displayed as 01–24) / 主题卡序号(显示为 01-24) |
progress |
String/Number |
null |
Lightning: travel percent 0–100 (bolt positioned at that % of card width, random drift disabled). Liquid: flow strength target 0–100. Both update with smooth transitions / 闪电:游走百分比 0-100(闪电定位在该百分比处,禁用随机游走);流体:流动强度目标 0-100。更新时平滑过渡 |
fluid |
Boolean |
false |
Width fills parent container / 宽度占满父容器 |
width / height |
Number/String |
null |
Custom width/height (passing one is enough; aspect ratio ignored when height is passed; the picture stretches to fill when both are forced) / 自定义宽/高(传其一即可,传 height 时忽略宽高比;两者同时强制时画面拉伸填满) |
cornerRadius |
Number/String |
null |
Corner radius as a ratio of card height (e.g. 0.1 = 10% height, 0.5 = pill). Falls back to CARD_GEOMETRY.cornerRadius (0.1) when unset / 圆角比例(相对卡片高度,如 0.1 = 10% 高度,0.5 = 胶囊)。不传则用 CARD_GEOMETRY.cornerRadius(0.1) |
centralTitle |
String |
"" |
Centered title text, shown in the exact middle of the card (takes precedence over all other overlays) / 中央标题文字,在卡片内上下左右居中显示(优先于其他覆盖层) |
| Event / 事件 | Payload | Description / 说明 |
|---|---|---|
progress-change |
Number |
When progress is set, emits the current smoothed bolt position / flow speed percent (0–100) every frame — use it to display a value perfectly in sync with the card (e.g. @progress-change="live = $event" then :big-number="${Math.round(live)}%") / 设置 progress 时每帧回传当前平滑后的百分比(0~100),可用于展示与卡片状态完全同步的数值 |
When any stats prop is present, the stats layout replaces the card's default text content:
任意一个统计属性存在即显示统计布局,替代该卡默认文案:
<LightningCard
name="Current Pulse"
title="New Today" <!-- First column title: left-aligned, vertically centered / 第一列主题:靠左上下居中 -->
subtitle="+12.5% vs yesterday" <!-- Subtitle: left-aligned, below title / 副标题:靠左,主题下方 -->
big-number="1,024" <!-- Second column big number: centered / 第二列大数字:左右/上下居中 -->
/>| Property / 属性 | Type / 类型 | Description / 说明 |
|---|---|---|
title |
String |
First column title (left-aligned, vertically centered) / 第一列主题(靠左上下居中) |
subtitle |
String |
Subtitle (below title) / 副标题(主题下方) |
bigNumber |
String/Number |
Second column big number (centered) / 第二列大数字(居中) |
central-title displays text centered both horizontally and vertically inside the card, replacing all other overlays:
central-title 在卡片内上下左右居中显示文字,替代其他所有覆盖层:
<LightningCard name="Current Pulse" central-title="闪电卡片" width="100px" height="30px" corner-radius="0.5" />The corner radius is a ratio of the card height, applied in two layers: the shader SDF alpha (card picture itself) and CSS clipping (container). Both stay in sync and scale with the card size.
圆角为卡片高度的比例,双层实现:shader SDF alpha(卡片画面本身)与 CSS 裁剪(容器),两者同步且随卡片尺寸缩放。
<LightningCard name="Current Pulse" corner-radius="0.1" /> <!-- 10% of height / 10% 卡片高度 -->
<LiquidMixingCard name="Sunset" corner-radius="0.5" /> <!-- Pill shape / 胶囊 -->src/App.vue renders a header with two clickable mini-cards that switch between two views:
src/App.vue 的顶栏放置两张可点击的迷你卡片,点击切换两个页面:
- LightningCardView — hero card + stats cards + 24 theme card grid / 主图 + 统计卡 + 24 张主题卡网格
- LiquidMixingCardView — main card + stats cards + 24 theme card grid / 主卡 + 统计卡 + 24 张主题卡网格
src/
├── main.js # App entry / 应用入口
├── App.vue # Demo page: two-view navigation / 演示页:双视图导航
├── style.css # Tailwind CSS entry + theme / Tailwind CSS 入口 + 主题
├── components/
│ ├── LightningCard.vue # Lightning card component / 闪电卡片组件
│ └── LiquidMixingCard.vue # Liquid mixing card component / 流体混合卡片组件
├── views/
│ ├── LightningCardView.vue # Lightning demo view / 闪电演示页
│ └── LiquidMixingCardView.vue # Liquid mixing demo view / 流体混合演示页
├── config/
│ ├── lightning-cards.js # Lightning config hub: names, colors, shapes, animation params / 闪电配置中心
│ └── liquid-mixing-cards.js # Liquid mixing config hub / 流体混合配置中心
├── shaders/
│ ├── liquid-lightning.js # Hero shader factory (liquid-lightning algorithm) / 主图材质工厂(liquid-lightning 算法)
│ ├── liquid-style-material.js # 24-theme shader factory (liquid-style algorithm) / 24 套主题材质工厂(liquid-style 算法)
│ └── liquid-mixing-material.js # Liquid mixing shader factory (domain-warped FBM) / 流体混合材质工厂(域扭曲 FBM)
└── lib/
└── shared-renderer.js # Shared WebGL renderer (single context + region-based copy) / 共享 WebGL 渲染器(单上下文 + 分区域拷贝)
All card parameters are centralized in src/config/lightning-cards.js and src/config/liquid-mixing-cards.js. Each card is keyed by its English name with a complete configuration:
所有卡片参数集中在 src/config/lightning-cards.js 与 src/config/liquid-mixing-cards.js,每张卡片以其英文名为 key 挂载完整配置:
name/description— English name / Chinese summary / 英文名称 / 中文简介algorithm— Shader algorithm (liquid-lightninghero /liquid-styletheme card /liquid-mixingtheme card) / 着色器算法(liquid-lightning主图 /liquid-style主题卡 /liquid-mixing主题卡)layout— Geometry params (card world size / camera FOV / width) / 几何参数(卡片世界尺寸 / 相机 FOV / 宽度)material— Shader shape params (colors and lightning shape) / 着色器形态参数(配色与闪电形态)animation— GSAP orchestration params (reveal / travel / flicker / strike / speed / flow) / GSAP 调度参数(reveal / travel / flicker / strike / speed / flow)content/overlay— Main card text overlay content and entrance animation / 主卡文案覆盖层内容与入场动画
To add a new theme card, simply add an entry to the config — no component changes needed.
新增一张主题卡只需在配置中心加一项,组件无需任何改动。
- Shared Renderer (
src/lib/shared-renderer.js): One hidden canvas + oneTHREE.WebGLRenderer, rendering all card scenes via scissor/viewport regions, copying back to each card's own 2D canvas per frame (2D contexts have no count limit). The shared canvas auto-wraps into columns when height exceeds 4096 to stay within GPU viewport limits. - 共享渲染器(
src/lib/shared-renderer.js):1 个隐藏 canvas + 1 个THREE.WebGLRenderer,按 scissor/viewport 分区域渲染所有卡片场景,每帧拷贝回各卡片自身的 2D canvas(2D 上下文无数量限制)。共享画布高度超 4096 自动换列,避免超出 GPU 视口限制 - Velocity-tracked Motion Trail: JS frame deltas are first low-pass filtered (
smoothing), then tanh-compressed (tanhScale), and finally accumulated into a flowing phase — preventing global time in the shader from amplifying frame-difference noise. - 速度跟踪拖尾:JS 帧差先经低通滤波(
smoothing),再经 tanh 压缩(tanhScale)后累积为流动相位,避免 shader 里全局时间放大帧差噪声 - Dual-Seed Morphing: On strike, a new
uBoltSeedis generated anduSeedMixsmoothly transitions 0→1 during the flash decay phase, morphing the lightning from its old shape into a brand-new random shape. - 双种子变形:闪击触发时生成新
uBoltSeed,uSeedMix在闪光衰减期 0→1 平滑过渡,闪电从旧形状变形为全新随机形状 - Corner Radius: A single
cornerRadiusRatiosource drives both the CSSborder-radius(converted from the container's actual height inresize()) and the shader round-box SDF alpha (uCornerRadiusuniform), so the picture and the clipping stay pixel-consistent. - 圆角实现:单一
cornerRadiusRatio数据源同时驱动 CSSborder-radius(在resize()中按容器实际高度换算)与 shader 圆角盒 SDF alpha(uCornerRadiusuniform),画面与裁剪像素级一致
- Vue 3 + Vite — Framework & build tooling / 框架与构建
- Three.js — WebGL rendering / WebGL 渲染
- GSAP — Animation orchestration / 动画调度
- Tailwind CSS v4 — Styling / 样式
Special thanks to the shuke-lab-flux project for its inspiration — the domain-warped FBM cloud rendering approach and flow interaction model of LiquidMixingCard are ported and re-architected from it.
特别感谢 shuke-lab-flux 项目的启发——LiquidMixingCard 的域扭曲 FBM 云雾渲染与流动交互模型移植并重构自该项目。
