MetalFx
按钮、文字与徽标的 WebGL2 液态金属材质
用法
基础
TxMetalFx 包裹恰好一个宿主元素,在 WebGL2 画布上为它绘制金属环。
示例加载中...
变体
button 是 1 px 环的胶囊,circle 是 2 px 环的正圆;环半径取自子元素的 border-radius。
<template>
<TxMetalFx variant="button" preset="silver" :strength="0.7">
<a href="/pricing">升级到 Pro</a>
</TxMetalFx>
<TxMetalFx variant="circle" preset="gold" inner-shadow :scale="1.5">
<button type="button" aria-label="发送">↑</button>
</TxMetalFx>
</template>
文字与徽标
TxMetalText 与 TxMetalBadge 固定使用 chromatic 材质,并以自身文本作为 aria-label。
<template>
<TxMetalText font="600 32px/1.1 Inter, sans-serif" color="#e8e8e8">Pro</TxMetalText>
<TxMetalBadge>Beta</TxMetalBadge>
</template>
最佳实践
- 图标类子元素显式给出宽高;包裹层是
inline-flex,尺寸跟随子元素。 - 子元素背景保持透明,自定义填充写在
TxMetalFx上。 - 每页只用一个预设与主题:所有实例共用一份材质,最后应用的生效。
- 金属元素彼此拉开,并排的两个金属按钮会争夺视觉焦点。
reflectionTargets只传能持有引用的稳定邻元素。
API 参考
TxMetalFx
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
variant | 'button' | 'circle' | 'button' | 环基线:胶囊 1 px,圆形 2 px。 |
preset | 'chromatic' | 'silver' | 'gold' | 'chromatic' | 金属颜色,每个预设都有明暗两套调校。 |
theme | 'auto' | 'dark' | 'light' | 'auto' | 预设的明暗侧;auto 实时跟随系统。 |
strength | number | 1 | 同时缩放着色器不透明度与辉光 alpha(0-1)。 |
glowGain | number | 1 | 仅作用于辉光的倍数,相乘后钳制到 0-1。 |
paused | boolean | false | 冻结在当前帧。 |
borderRadius | number | 自动探测 | 环半径(CSS px)。 |
normalizeHostStyles | boolean | true | 剥离子元素的边框、outline 与 box-shadow。 |
reflectionTargets | Array<Element | { ref, strength }> | 无 | 接收镜像反射的邻元素。 |
disableGlow | boolean | false | 移除游走辉光,保留金属环。 |
innerShadow | boolean | { offsetY, blur, alpha, color } | 关 | 环顶部内侧的高光边。 |
shaderScale | number | 变体基线 × scale | 覆盖着色器采样尺度。 |
ringCssPx | number | 变体基线 × scale | 覆盖环厚度(CSS px)。 |
scale | number | 1 | 引擎内所有绝对像素常量的总倍数。 |
mask | (ctx, size) => void | 无 | 自定义 alpha 遮罩,着色器只保留遮罩覆盖处。 |
glowMode | 'mask' | 'ring' | 'mask' | 设置 mask 后辉光的落位方式。 |
插槽
| 插槽 | 参数 | 说明 |
|---|---|---|
default | - | 恰好一个宿主元素,保留其自身事件处理。 |
CSS 变量
| 变量 | 来源 | 说明 |
|---|---|---|
--mfx-strength | strength | 钳制到 0-1 的强度,供下游 CSS 读取。 |
--mfx-radius | borderRadius 或自动探测 | 环半径(px)。 |
TxMetalText
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
font | string | 必填 | CSS font 简写。 |
color | string | 必填 | 金属下方的底色。 |
strength | number | 1 | 金属不透明度。 |
reflectionTargets | Array<Element | { ref, strength }> | 无 | 接收金属反射的邻元素。 |
children | string | 无 | 默认插槽为空时的文本。 |
theme | 'auto' | 'dark' | 'light' | 无 | 预设的明暗侧;未传时跟随系统。 |
innerShadow | TextInnerShadow | null | FIGMA_INNER_SHADOW | 字形内侧顶部的高光边;null 关闭。 |
glow | boolean | false | 在字形上显示辉光。 |
glowGain | number | 2.5 | glow 开启时的辉光倍数。 |
metalOpacity | number | 0.62 | 金属盖过底色的程度(0-1),与 strength 相乘。 |
shaderScale | number | 2.8 | 字形内金属纹理的缩放。 |
插槽
| 插槽 | 参数 | 说明 |
|---|---|---|
default | - | 标签文本。 |
TxMetalBadge
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
children | string | 'New' | 默认插槽为空时的文本。 |
strength | number | 1 | 金属不透明度。 |
theme | 'auto' | 'dark' | 'light' | 无 | 预设的明暗侧;未传时跟随系统。 |
scale | number | 1 | 整体尺寸倍数(基准 45×25)。 |
reflectionTargets | Array<Element | { ref, strength }> | 无 | 接收金属反射的邻元素。 |
metalOpacity | number | 0.8 | 金属盖过白底的程度(0-1),与 strength 相乘。 |
shaderScale | number | 1.6 | 金属纹理的缩放。 |
core | MetalBadgeCore | { r: 46, blur: 100, a: 0.94, size: 49 } | 文字下白色核心的半径、过渡、不透明度与尺寸。 |
gradient | number | 0 | 自上而下的白色渐变强度(0-1)。 |
glow | number | 0.41 | 内侧白色辉光强度(0-1)。 |
textColor | string | '#323232' | 文字颜色。 |
插槽
| 插槽 | 参数 | 说明 |
|---|---|---|
default | - | 标签文本,为空时用 children。 |
概述
- 全页实例共用一个 WebGL2 上下文、一份材质和一个约 15 fps 的循环;离屏实例(
IntersectionObserver,64 px 边距)不渲染,标签页隐藏时循环停止。 - 首帧金属绘制完成前,包裹层连同子元素不可见;在那之前不要测量或动画化子元素。
- 反射只在暗色主题渲染;亮色主题下不扫描 DOM,也没有逐帧开销。
- 着色器不响应减少动态效果,需要时自行传
paused(可选disableGlow)。 - 光标反射需经
setCursorSprite注册精灵图,否则保持关闭;减少动态效果、forced-colors与粗指针下自动关闭。 - 不支持 WebGL2 时,子元素保留自身样式,渲染在
div.metal-fx-fallback[data-metal-fx-unsupported]中,不画环。
技术实现
engine/**逐字移植自 Jakubantalik/Libraries · metal-fx v2(MIT © Jakub Antalik),Vue 壳沿用 React 包裹层的生命周期、测量与清理。- 页面级调校使用模块导出的引擎原语:
setGlowConfig、setCursorLightConfig、setBendConfig、isMetalFxSupported等。 - 源码:
packages/tuffex/packages/components/src/metal-fx/。
查看源码
packages/tuffex/packages/components/src/metal-fx/index.ts