组件
文本波光 Text Shimmer Wave
逐字符传播的立体位移与高光波浪。
基础用法
Loading…
pnpm dlx @wui-design/cli@latest add @wui/text-shimmer-wave"use client"
import * as React from "react"
import { motion, useReducedMotion, type Transition } from "motion/react"
import { cn } from "@/lib/utils"
export interface TextShimmerWaveProps extends React.ComponentProps<"span"> {
/** Text animated as a traveling character wave. */
children: string
/** HTML element rendered by the component. @default "span" */
as?: React.ElementType
/** Seconds for one full wave. @default 1.5 */
duration?: number
/** Z-axis travel in pixels. @default 10 */
zDistance?: number
/** Horizontal travel in pixels. @default 2 */
xDistance?: number
/** Vertical travel in pixels. @default -2 */
yDistance?: number
/** Distance between character wave phases. @default 1 */
spread?: number
/** Peak character scale. @default 1.1 */
scaleDistance?: number
/** Peak Y-axis rotation in degrees. @default 10 */
rotateYDistance?: number
/** Motion transition merged into every character. */
transition?: Transition
}
/** Sends a shimmer-like 3D wave through text, one character at a time. */
function TextShimmerWave({
children,
as = "span",
duration = 1.5,
zDistance = 10,
xDistance = 2,
yDistance = -2,
spread = 1,
scaleDistance = 1.1,
rotateYDistance = 10,
transition,
className,
...props
}: TextShimmerWaveProps) {
const Component = as
const reduceMotion = useReducedMotion()
return (
<Component
data-slot="text-shimmer-wave"
className={cn("inline-flex [perspective:400px]", className)}
{...props}
>
<span className="sr-only">{children}</span>
{Array.from(children).map((character, index) => (
<motion.span
aria-hidden="true"
data-slot="text-shimmer-wave-character"
className="text-muted-foreground inline-block whitespace-pre"
key={`${character}-${index}`}
animate={
reduceMotion
? undefined
: {
color: [
"var(--muted-foreground)",
"var(--foreground)",
"var(--muted-foreground)",
],
x: [0, xDistance, 0],
y: [0, yDistance, 0],
z: [0, zDistance, 0],
scale: [1, scaleDistance, 1],
rotateY: [0, rotateYDistance, 0],
}
}
transition={{
duration,
ease: "easeInOut",
repeat: Infinity,
delay: (index * duration * 0.08) / Math.max(spread, 0.1),
...transition,
}}
>
{character === " " ? "\u00a0" : character}
</motion.span>
))}
</Component>
)
}
export { TextShimmerWave }
使用场景
TextShimmerWave 把颜色、位移、缩放和轻微旋转组合成逐字符波浪。它比普通扫光更醒目,适合短暂生成状态或单一展示焦点;
不要在同一视口放置多个波浪文本。
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| children * | string | — | 按字符播放立体波浪动画的文字。 |
| as | ElementType<any, keyof IntrinsicElements> | span | 组件实际渲染的 HTML 元素。 |
| duration | number | 1.5 | 完整波浪动画循环的时长,单位为秒。 |
| zDistance | number | 10 | 字符沿 Z 轴移动的距离,单位为像素。 |
| xDistance | number | 2 | 字符沿水平方向移动的距离,单位为像素。 |
| yDistance | number | -2 | 字符沿垂直方向移动的距离,单位为像素。 |
| spread | number | 1 | 相邻字符波浪相位之间的距离。 |
| scaleDistance | number | 1.1 | 字符达到的最大缩放比例。 |
| rotateYDistance | number | 10 | 字符达到的最大 Y 轴旋转角度,单位为度。 |
| transition | Transition | — | 合并到每个字符上的过渡动画。 |
属性名后的 * 表示必填。
事件
组件没有自有事件,底层元素事件继续透传。用户开启“减少动态效果”时只显示静态文字。
扩展用法
xDistance、yDistance、zDistance 控制空间位移,scaleDistance 和 rotateYDistance 控制形变。使用自定义 transition 时,
建议保持较小的位移和旋转,避免文字难以阅读。
无障碍
组件内部保留一份视觉隐藏(sr-only)的完整文本,逐字符动画的 span 对读屏工具隐藏,整句只会被朗读一次。