组件
动态图标 Animated Icon
图标内部路径会随交互运动的 Lucide 动态图标集合。
基础示例
这些不是对整个 SVG 做统一缩放或旋转。每个图标都有独立的逐路径动画,例如铃铛摆动、复制层分离、菜单线条重排和齿轮转动。
Loading…
安装完整集合:
pnpm dlx wui@latest add @wui/animated-icon-collection完整集合包含 AnimateIcons 的 248 个图标和 ItsHover 去重后独有的 207 个图标,共 455 个;56 个同名重复图标只保留 AnimateIcons 版本。安装命令会同时加入 @animateicons/react、本地 ItsHover 图标源码和统一适配组件。
"use client"
import * as React from "react"
export interface AnimatedIconHandle {
startAnimation: () => void
stopAnimation: () => void
}
export interface AnimatedIconGlyphProps extends Omit<
React.HTMLAttributes<HTMLDivElement>,
| "color"
| "onAnimationEnd"
| "onAnimationIteration"
| "onAnimationStart"
| "onDrag"
| "onDragEnd"
| "onDragStart"
> {
size?: number
duration?: number
isAnimated?: boolean
color?: string
}
export type AnimatedIconGlyph = React.ForwardRefExoticComponent<
AnimatedIconGlyphProps & React.RefAttributes<AnimatedIconHandle>
>
export interface AnimatedIconProps extends AnimatedIconGlyphProps {
/** Path-animated icon imported from `@animateicons/react/lucide`. */
icon: AnimatedIconGlyph
/** Accessible name. Omit it when the icon is purely decorative. */
label?: string
/** Imperative playback handle exposed by the animated glyph. */
ref?: React.Ref<AnimatedIconHandle>
}
/**
* A common accessible adapter for path-animated icons from AnimateIcons.
* Every glyph keeps its own semantic motion and imperative playback handle.
*/
function AnimatedIcon({
icon: Glyph,
label,
ref,
...props
}: AnimatedIconProps) {
return (
<Glyph
ref={ref}
data-slot="animated-icon"
aria-hidden={label ? undefined : true}
aria-label={label}
role={label ? "img" : undefined}
{...props}
/>
)
}
export { AnimatedIcon }
动态图标库
悬停或键盘聚焦任意图标即可预览动画,点击会复制对应来源的按需导入语句。可以在“全部 / AnimateIcons / ItsHover”之间切换。
455 / 455 个逐路径动态图标
直接使用
import { BellRingIcon, CopyIcon } from "@animateicons/react/lucide"
import {
AirplaneIcon,
BrandOpenaiIcon,
} from "@/components/ui/animated-icons"
<BellRingIcon size={24} />
<CopyIcon size={24} duration={0.7} />
<AirplaneIcon size={24} />
<BrandOpenaiIcon size={24} />每个图标默认在自身悬停时播放。如果交互区域比图标大,例如工具栏按钮或菜单项,可以使用 wui 的 AnimatedIcon 统一处理无障碍语义,并通过 ref 让父元素启动动画。
从父元素控制
"use client"
import { useRef } from "react"
import { BellRingIcon } from "@animateicons/react/lucide"
import {
AnimatedIcon,
type AnimatedIconHandle,
} from "@/components/ui/animated-icon"
export function Notifications() {
const iconRef = useRef<AnimatedIconHandle>(null)
return (
<button
aria-label="通知"
onMouseEnter={() => iconRef.current?.startAnimation()}
onMouseLeave={() => iconRef.current?.stopAnimation()}
onFocus={() => iconRef.current?.startAnimation()}
onBlur={() => iconRef.current?.stopAnimation()}
>
<AnimatedIcon ref={iconRef} icon={BellRingIcon} size={24} />
</button>
)
}startAnimation() 与 stopAnimation() 适合按钮、菜单项、保存状态等由父元素控制的场景。组件会保留每个图标自己的动画编排,不会覆盖成统一的动效模板。
减少动态效果
AnimateIcons 会读取用户的减少动态效果偏好;本地化的 ItsHover
图标通过统一导出层停止悬停和命令式播放。请从 @/components/ui/animated-icons
导入 ItsHover 图标,不要绕过入口直接引用内部文件。
图标来源
- AnimateIcons:248 个主集合图标,MIT 许可,通过 npm 按需导入。
- ItsHover:本地化 207 个去重后的补充图标,保留 Apache 2.0 许可证和来源说明。
品牌图标的源码许可不代表获得对应品牌的商标授权,实际产品使用前仍需核对品牌规范。
组件属性
| Prop | Type | Default | Description |
|---|---|---|---|
| icon * | AnimatedIconGlyph | — | Path-animated icon imported from `@animateicons/react/lucide`. |
| label | string | — | Accessible name. Omit it when the icon is purely decorative. |
| ref | Ref<AnimatedIconHandle> | — | Imperative playback handle exposed by the animated glyph. |
| size | number | — | |
| duration | number | — | |
| isAnimated | boolean | — |