Ant Design BorderBeam 动画时长:用 duration 属性控制边框流光节奏的完整解析
本篇指南围绕 Ant Design BorderBeam(边框流光)组件的 duration 属性展开,讲清楚它如何控制流光完成一圈动画所需的时间,并在当前仓库源码层面说明该属性如何经由 CSS 变量落到 animation-duration、如何参与多条流光(count)的错峰延迟计算,以及默认值 6 秒的来源。读完你可以直接在自己的项目中配置合理的流光节奏,并理解其降级与无效值回退行为。
duration 是什么:一句话定义
在官方示例说明文档 duration.md 中,duration 的定义非常明确:
通过
duration控制流光完成一圈所需时间,单位为秒,默认值为 6 秒。
即流光(beam)沿容器边框环绕一周所耗费的秒数。对应组件 API 表中(见 index.zh-CN.md):
| 参数 | 说明 | 类型 | 默认值 | 版本 | 全局配置 |
|---|---|---|---|---|---|
| duration | 流光完成一圈动画的时间,单位秒 | number |
6 |
6.5.0 | × |
注意两点事实前提:
duration属于BorderBeam组件属性,随 6.5.0 版本引入(组件本身是 6.4.0 新增);- 它不支持
ConfigProvider的组件级全局配置(API 表“全局配置”列为 ×),只能逐实例通过属性传入。
官方示例:三种节奏的对照演示
配套示例 duration.tsx 用三张 Card 并排展示了 3 种典型时长,这也是理解取值语义的最佳入口:
import React from 'react';
import { BorderBeam, Card, Flex, Tag, Typography } from 'antd';
const durations = [
{
name: 'Fast',
seconds: 3,
description: 'A quick loop for temporary highlights and active modules.',
},
{
name: 'Default',
seconds: 6,
description: 'The original pacing for most emphasized containers.',
},
{
name: 'Slow',
seconds: 12,
description: 'A calmer loop for persistent panels and ambient surfaces.',
},
];
const App: React.FC = () => (
<Flex gap={16} wrap>
{durations.map(({ name, seconds, description }) => (
<div key={name} style={{ width: 220 }}>
<BorderBeam duration={seconds}>
<Card title={name} extra={<Tag variant="filled">{seconds}s</Tag>}>
<Typography.Text type="secondary">{description}</Typography.Text>
</Card>
</BorderBeam>
</div>
))}
</Flex>
);
export default App;
示例给出的取值语义可以总结为:
- 3 秒(Fast):快速循环,适合临时性高亮、正在激活的模块;
- 6 秒(Default):默认节奏,适合大多数需要强调的容器;
- 12 秒(Slow):更沉稳的循环,适合常驻面板、氛围型背景表面。
从示例快照(demo-extend.test.ts.snap)可以验证,这三个卡片最终分别生成了 --ant-border-beam-duration: 3s、6s、12s 的内联 CSS 变量,与传入值一一对应。
源码实现:duration 如何变成 CSS 动画时长
1. 默认值与合法性校验
默认值常量定义在 util.ts 中:
export const DEFAULT_BORDER_BEAM_DURATION = 6;
在组件主文件 BorderBeam.tsx 中,传入值会先经过一次合法性归一化:
const mergedDuration =
isNumber(duration) && duration > 0 ? duration : DEFAULT_BORDER_BEAM_DURATION;
也就是说,只有“是数字且大于 0”的 duration 才会被采纳,否则一律回退到 6 秒。这意味着:
- 传
0、负数、NaN、字符串或undefined都不会报错,而是静默使用默认值; mergedDuration只用于内部计算(如多条流光的错峰),不直接决定最终样式。
2. 通过 CSS 变量注入内联样式
真正把 duration 写到 DOM 上的,是渲染时对内联 style 的条件展开:
...(isNumber(duration) && duration > 0 && { [varName('duration')]: `${duration}s` }),
只有当 duration 是合法正数时,才会设置 --ant-border-beam-duration(变量前缀随主题 hash 变化,varName 由 genCssVar 生成),并以秒为单位拼接 s 后缀。若不传该属性,这个 CSS 变量根本不会写入,样式层会取到兜底默认值——这就是“不传 duration 也是 6 秒”的实现方式。
3. 样式层:animation-duration 的落点
在样式文件 style/index.ts 中,流光动画本体由 ::before 伪元素承载:
const antBorderBeamMove = new Keyframes('antBorderBeamMove', {
from: { offsetDistance: '0%' },
to: { offsetDistance: '100%' },
});
关键帧基于 CSS Motion Path 的 offset-path/offset-distance:一个边长为 size 的方形渐变层(offsetPath: rect(0 auto auto 0 round ...))沿容器边框路径从 0% 移动到 100%,配合 @supports (offset-path: rect(...)) 特性探测,在不支持该特性的浏览器中整个流光层保持 display: none 静默降级。动画属性如下:
'&::before': {
...
animationName: antBorderBeamMove,
animationDuration: varRef('duration', `${DEFAULT_BORDER_BEAM_DURATION}s`),
animationDelay: varRef('delay', '0s'),
animationTimingFunction: 'linear',
animationIterationCount: 'infinite',
willChange: 'offset-distance',
}
注意 varRef('duration', '6s'):duration 属性最终就是这里 animation-duration 的 CSS 变量来源,默认兜底同样来自 DEFAULT_BORDER_BEAM_DURATION。由于 animationTimingFunction 是 linear 且循环 infinite,duration 越大整体观感越平缓,越小越急促——与示例中 Fast/Default/Slow 的语义完全一致。
duration 与 count 的联动:多条流光的错峰延迟
duration 并非孤立存在,它与 count(流光数量,6.6.0 引入)共同决定多条流光的相位分布。仍在 BorderBeam.tsx 中:
...(index > 0 && {
[varName('delay')]: `${(-mergedDuration * index) / mergedCount}s`,
}),
第 index 条流光(从 1 开始)的动画延迟为 -duration × index / count。负延迟使所有流光在页面加载瞬间即处于循环的不同相位,均匀分布在一圈内。
这一点被单测直接固化(见 index.test.tsx):
rerender(
<BorderBeam count={3} duration={12}>
<div>content</div>
</BorderBeam>,
);
expect(getBeamElements(container)).toHaveLength(3);
// 三条流光各自的 animation-delay
expect(...).toEqual(['', '-4s', '-8s']);
即 count=3、duration=12 时,三条流光的延迟依次为 0s、-4s、-8s(12 ÷ 3 = 4 秒一档)。由此可以得到一个实用的调参结论:调大 duration 时若想保持多条流光的均匀间隔感,无需额外处理——错峰延迟会随 duration 等比放大,视觉上依然是均匀分布。
同一测试文件还验证了 duration=12 时 beam 元素的 --ant-border-beam-duration 为 12s,而移除该属性后变量被清空、回落到样式层默认的 6 秒。
失效边界与降级行为
理解 duration 的完整行为,还需要知道两条“不出效果”的边界,均能从样式源码确认(style/index.ts):
- CSS 特性不支持:流光依赖
mask-composite与offset-path: rect(...),任一不支持时组件通过@supports门控保持display: none,duration自然无从生效,但不会破坏页面布局(流光层本身position: absolute、pointer-events: none,不干扰内容交互)。 - 减少动态效果偏好:命中
prefers-reduced-motion: reduce时,::before被显式display: none,同时 genNoMotionRawStyle 将transition/animation置为none。官方文档 FAQ 也明确:BorderBeam将流光视为装饰效果,用户系统开启减少动态效果时 beam 会被隐藏。此时duration的取值没有意义,属于预期行为而非缺陷。
另外,流光层通过 createPortal 插入到 children 对应的真实 DOM 节点中(见 BorderBeamEffect.tsx),因此被包裹的内容必须是原生 DOM 元素或正确透传 ref 的组件,否则组件拿不到宿主节点,直接不渲染流光层——这一点在 index.zh-CN.md 的 FAQ “为什么 BorderBeam 没有效果?” 中也有说明,排查 duration 不生效时应优先确认流光本身是否已渲染。
使用建议与小结
duration的单位是秒,类型必须是数字;0、负数等非正数值会被静默回退为默认 6 秒,建议在业务代码中只传有意义的正数(如 3 / 6 / 12);- 临时强调、激活态高亮建议取较短值(3 秒上下),常驻氛围效果建议取较长值(10 秒以上),避免视觉疲劳;
- 与
count搭配时不必单独考虑相位:组件会按-duration × index / count自动均分,duration只决定整体快慢; - 该属性自 6.5.0 起可用,且不支持
ConfigProvider全局配置,需要按实例传递; - 完整属性(
color、size、lineWidth、outset等)以 index.zh-CN.md 的 API 表为准,更多示例可参考 demo 目录 下的basic、hover、count等演示。
一句话总结:duration 是 BorderBeam 流光动画的节奏旋钮——它经由内联 CSS 变量 --ant-border-beam-duration 映射到 ::before 伪元素的 animation-duration,默认 6 秒,非法值自动回退,并会按比例参与多条流光的错峰延迟计算。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00