@yqg/aminofx-kit
v1.0.3
Published
YQG AminoFX CSS animation kit - Core animation utilities and effects
Maintainers
Readme
动画播放器 SDK
一个强大、灵活的Web动画播放器SDK,支持基于关键帧的复杂动画制作和播放。
🚀 功能特性
- 关键帧动画: 基于时间轴的关键帧动画系统
- 模板引擎: 支持
{{variable}}语法的动态内容渲染 - 事件系统: 完整的动画生命周期和元素交互事件支持
- CSS变换: 支持位移、缩放、旋转、透明度等动画属性
- 缓动函数: 内置多种缓动函数,包括弹性和弹跳效果
- 状态管理: 完整的播放、暂停、停止、跳转控制
- 自适应时长: 根据关键帧自动计算动画时长
- 类型安全: 完整的TypeScript类型定义
📦 安装
npm install @yqg-max/click-gate🏗️ 核心接口
IAnimationElement
动画元素配置接口,定义了动画中每个元素的基本信息和样式。
interface IAnimationElement {
/** 元素唯一标识符 */
id: string;
/** 元素关联的数据,用于模板渲染 */
data?: Record<string, any>;
/** 元素内容配置 */
content: {
/** HTML内容模板,支持 {{variable}} 语法 */
html?: string;
/** 自定义CSS样式 */
style?: Record<string, string | number>;
};
}IPropertieCss
CSS属性接口,定义了动画中常用的CSS变换属性。
interface IPropertieCss {
/** X轴位置 (px) */
x: number;
/** Y轴位置 (px) */
y: number;
/** 宽度 (px) */
width: number;
/** 高度 (px) */
height: number;
/** 旋转角度 (deg) */
rotation: number;
/** 透明度 (0-1) */
opacity: number;
/** 缩放比例 */
scale: number;
}IAnimationKeyframe
动画关键帧接口,定义了某个时间点上元素的属性状态。
interface IAnimationKeyframe {
/** 关键帧唯一标识符 */
id: string;
/** 关联的元素ID */
elementId: string;
/** 时间点 (毫秒) */
time: number;
/** 该时间点的CSS属性值 */
properties: Partial<IPropertieCss> & Record<string, any>;
}IAnimationSchema
动画配置模式接口,定义了完整的动画配置。
interface IAnimationSchema {
/** 动画中的所有元素 */
elements: IAnimationElement[];
/** 动画中的所有关键帧 */
keyframes: IAnimationKeyframe[];
/** 全局数据,用于模板渲染 */
data?: Record<string, any>;
}IAnimationInfo
动画信息接口,提供动画的统计信息。
interface IAnimationInfo {
/** 总时长 (毫秒) */
totalDuration: number;
/** 最大关键帧时间 */
maxKeyframeTime: number;
/** 关键帧数量 */
keyframeCount: number;
/** 元素数量 */
elementCount: number;
/** 是否自动计算时长 */
isAutoCalculated: boolean;
}🎭 类型定义
EasingFunction
动画缓动函数类型。
type EasingFunction =
| 'linear' // 线性
| 'ease-in' // 缓慢开始
| 'ease-out' // 缓慢结束
| 'ease-in-out' // 缓慢开始和结束
| 'ease-in-cubic' // 三次方缓入
| 'ease-out-cubic' // 三次方缓出
| 'bounce-out' // 弹跳结束
| 'elastic-out'; // 弹性结束AnimationState
动画状态类型。
type AnimationState = 'idle' | 'playing' | 'paused' | 'completed';ElementEventCallback
事件监听器回调函数类型。
type ElementEventCallback = (event: Event, element: HTMLElement) => void;🎨 核心类
AnimationPlayer
动画播放器主类,负责管理和控制动画的播放。
构造函数
constructor(container: HTMLElement, schema: IAnimationSchema)播放控制方法
| 方法 | 描述 | 参数 | 返回值 |
| -------------------- | ------------------------ | ---------------------- | ------ |
| play() | 开始播放动画 | - | void |
| pause() | 暂停动画 | - | void |
| stop() | 停止动画并重置到初始状态 | - | void |
| seek(time: number) | 跳转到指定时间 | time: 目标时间(毫秒) | void |
状态查询方法
| 方法 | 描述 | 返回值 |
| -------------------- | ------------------ | ------------------ |
| getCurrentTime() | 获取当前播放时间 | number |
| getDuration() | 获取动画总时长 | number |
| getProgress() | 获取播放进度(0-1) | number |
| getState() | 获取当前状态 | AnimationState |
| isPlaying() | 检查是否正在播放 | boolean |
| getSchema() | 获取动画配置的副本 | IAnimationSchema |
| getAnimationInfo() | 获取动画统计信息 | IAnimationInfo |
数据更新方法
| 方法 | 描述 | 参数 |
| ------------------------- | ------------ | ----------------------- |
| updateData(newData) | 更新动画数据 | newData: 新数据对象 |
| updateSchema(newSchema) | 更新动画配置 | newSchema: 新配置对象 |
事件监听方法
| 方法 | 描述 | 参数 |
| ------------------------------------------ | ------------ | ------------------------------------------- |
| onTimeChange(callback) | 监听时间变化 | callback: (time: number) => void |
| onAnimationComplete(callback) | 监听动画完成 | callback: () => void |
| onStateChange(callback) | 监听状态变化 | callback: (state: AnimationState) => void |
| onListen(elementId, eventType, callback) | 监听元素事件 | 详见下表 |
onListen 参数详情
| 参数 | 类型 | 描述 |
| ----------- | ---------------------- | -------------------------------- |
| elementId | string | 元素ID |
| eventType | string | 事件类型('click', 'mouseover'等) |
| callback | ElementEventCallback | 事件回调函数 |
| 返回值 | () => void | 取消监听的函数 |
事件管理方法
| 方法 | 描述 | 参数 |
| ------------------------------- | ---------------------------- | ------------------- |
| removeAllListeners(elementId) | 移除指定元素的所有事件监听器 | elementId: 元素ID |
| removeAllElementListeners() | 移除所有事件监听器 | - |
| destroy() | 销毁动画播放器 | - |
TemplateEngine
模板引擎类,负责解析和渲染模板字符串。
静态方法
| 方法 | 描述 | 参数 | 返回值 |
| ------------------------ | -------------- | ------------------------------------------ | -------- |
| render(template, data) | 渲染模板字符串 | template: 模板字符串data: 渲染数据 | string |
CSSAnimationGenerator
CSS动画生成器类,负责生成CSS关键帧动画代码。
静态方法
| 方法 | 描述 | 参数 | 返回值 |
| --------------------------------------------------- | ----------------- | ----------------------------------------------------------------- | -------- |
| generateKeyframes(elementId, keyframes) | 生成CSS关键帧动画 | elementId: 元素IDkeyframes: 关键帧数组 | string |
| generateAnimationCSS(elementId, duration, easing) | 生成元素动画CSS | elementId: 元素IDduration: 动画时长easing: 缓动函数 | string |
| easingToCSSFunction(easing) | 转换缓动函数为CSS | easing: 缓动函数名 | string |
🏭 工厂函数
createAnimationPlayer
根据容器ID创建动画播放器。
function createAnimationPlayer(
containerId: string,
schema: IAnimationSchema,
): AnimationPlayer;createAnimationPlayerFromElement
直接使用DOM元素创建动画播放器。
function createAnimationPlayerFromElement(
container: HTMLElement,
schema: IAnimationSchema,
): AnimationPlayer;🎯 快速开始
基础示例
import { createAnimationPlayer, IAnimationSchema } from '@yqg-max/click-gate';
// 1. 定义动画配置
const schema: IAnimationSchema = {
elements: [
{
id: 'box1',
content: {
html: '<div style="width: 100px; height: 100px; background: #3b82f6;"></div>',
style: {
borderRadius: '8px',
},
},
},
],
keyframes: [
{
id: 'kf1',
elementId: 'box1',
time: 0,
properties: { x: 0, y: 0, opacity: 1, scale: 1 },
},
{
id: 'kf2',
elementId: 'box1',
time: 1000,
properties: { x: 200, y: 100, opacity: 0.5, scale: 1.5 },
},
{
id: 'kf3',
elementId: 'box1',
time: 2000,
properties: { x: 0, y: 0, opacity: 1, scale: 1, rotation: 360 },
},
],
};
// 2. 创建播放器
const player = createAnimationPlayer('animation-container', schema);
// 3. 播放动画
player.play();模板渲染示例
const schema: IAnimationSchema = {
data: {
title: '欢迎使用动画播放器',
subtitle: '强大而灵活的动画解决方案',
},
elements: [
{
id: 'text1',
data: {
content: '{{title}}',
},
content: {
html: '<h2>{{content}}</h2>',
style: {
color: '#1f2937',
fontFamily: 'Arial, sans-serif',
},
},
},
{
id: 'text2',
content: {
html: '<p>{{subtitle}}</p>',
style: {
color: '#6b7280',
},
},
},
],
keyframes: [
// 标题动画
{
id: 'title-start',
elementId: 'text1',
time: 0,
properties: { x: -200, opacity: 0 },
},
{
id: 'title-end',
elementId: 'text1',
time: 800,
properties: { x: 0, opacity: 1 },
},
// 副标题动画
{
id: 'subtitle-start',
elementId: 'text2',
time: 400,
properties: { x: 200, opacity: 0 },
},
{
id: 'subtitle-end',
elementId: 'text2',
time: 1200,
properties: { x: 0, opacity: 1 },
},
],
};事件监听示例
// 创建播放器
const player = createAnimationPlayer('container', schema);
// 监听元素点击事件
const removeClickListener = player.onListen(
'button1',
'click',
(event, element) => {
console.log('按钮被点击了!', element);
// 可以执行自定义逻辑
player.seek(1500); // 跳转到1.5秒
},
);
// 监听元素悬停事件
player.onListen('image1', 'mouseover', (event, element) => {
element.style.transform = 'scale(1.1)';
});
player.onListen('image1', 'mouseout', (event, element) => {
element.style.transform = 'scale(1)';
});
// 监听动画状态变化
player.onStateChange((state) => {
console.log('动画状态:', state);
});
// 监听播放进度
player.onTimeChange((time) => {
console.log('当前时间:', time);
});
// 监听动画完成
player.onAnimationComplete(() => {
console.log('动画播放完成!');
});动态数据更新示例
// 创建包含动态数据的动画
const schema: IAnimationSchema = {
data: {
username: 'User',
score: 0,
},
elements: [
{
id: 'scoreDisplay',
content: {
html: '<div class="score">{{username}}的分数: {{score}}</div>',
},
},
],
keyframes: [
{
id: 'score-anim',
elementId: 'scoreDisplay',
time: 0,
properties: { scale: 1 },
},
{
id: 'score-bounce',
elementId: 'scoreDisplay',
time: 500,
properties: { scale: 1.2 },
},
{
id: 'score-normal',
elementId: 'scoreDisplay',
time: 1000,
properties: { scale: 1 },
},
],
};
const player = createAnimationPlayer('container', schema);
// 动态更新数据
function updateScore(newScore: number) {
player.updateData({ score: newScore });
player.seek(0); // 重新播放动画
player.play();
}
// 使用示例
updateScore(100);
updateScore(250);🎪 高级用法
复杂动画序列
const complexSchema: IAnimationSchema = {
elements: [
{ id: 'circle', content: { html: '<div class="circle"></div>' } },
{ id: 'square', content: { html: '<div class="square"></div>' } },
{ id: 'triangle', content: { html: '<div class="triangle"></div>' } },
],
keyframes: [
// 圆形动画序列
{
id: 'c1',
elementId: 'circle',
time: 0,
properties: { x: 0, y: 0, opacity: 0 },
},
{
id: 'c2',
elementId: 'circle',
time: 500,
properties: { x: 100, y: 0, opacity: 1 },
},
{
id: 'c3',
elementId: 'circle',
time: 1000,
properties: { x: 100, y: 100, rotation: 180 },
},
{
id: 'c4',
elementId: 'circle',
time: 1500,
properties: { x: 0, y: 100, scale: 1.5 },
},
{
id: 'c5',
elementId: 'circle',
time: 2000,
properties: { x: 0, y: 0, scale: 1, rotation: 360 },
},
// 方形动画序列(延迟启动)
{
id: 's1',
elementId: 'square',
time: 300,
properties: { x: 200, y: 0, opacity: 0 },
},
{
id: 's2',
elementId: 'square',
time: 800,
properties: { x: 300, y: 0, opacity: 1 },
},
{
id: 's3',
elementId: 'square',
time: 1300,
properties: { x: 300, y: 100, rotation: 90 },
},
{
id: 's4',
elementId: 'square',
time: 1800,
properties: { x: 200, y: 100, scale: 0.8 },
},
// 三角形动画序列(更晚启动)
{
id: 't1',
elementId: 'triangle',
time: 600,
properties: { x: 400, y: 50, opacity: 0 },
},
{
id: 't2',
elementId: 'triangle',
time: 1100,
properties: { x: 450, y: 50, opacity: 1 },
},
{
id: 't3',
elementId: 'triangle',
time: 1600,
properties: { x: 450, y: 100, rotation: 120 },
},
{
id: 't4',
elementId: 'triangle',
time: 2100,
properties: { x: 400, y: 100, scale: 1.2 },
},
],
};自定义缓动函数
// 使用不同的缓动函数创建丰富的动画效果
const bounceSchema: IAnimationSchema = {
elements: [{ id: 'bouncer', content: { html: '<div class="ball"></div>' } }],
keyframes: [
{
id: 'bounce-start',
elementId: 'bouncer',
time: 0,
properties: { y: 0 },
},
{
id: 'bounce-drop',
elementId: 'bouncer',
time: 1000,
properties: { y: 200 }, // 使用 bounce-out 缓动
},
{
id: 'bounce-up',
elementId: 'bouncer',
time: 1500,
properties: { y: 50 }, // 弹起
},
{
id: 'bounce-settle',
elementId: 'bouncer',
time: 2000,
properties: { y: 200 }, // 最终落地
},
],
};📝 API 参考
动画播放器 API
播放控制
play()- 播放动画pause()- 暂停动画stop()- 停止动画seek(time: number)- 跳转到指定时间
状态查询
getCurrentTime(): number- 当前播放时间getDuration(): number- 动画总时长getProgress(): number- 播放进度 (0-1)getState(): AnimationState- 当前状态isPlaying(): boolean- 是否正在播放
数据管理
updateData(data: Record<string, any>)- 更新动画数据updateSchema(schema: IAnimationSchema)- 更新动画配置getSchema(): IAnimationSchema- 获取当前配置getAnimationInfo(): IAnimationInfo- 获取动画信息
事件监听
onTimeChange(callback)- 时间变化事件onAnimationComplete(callback)- 动画完成事件onStateChange(callback)- 状态变化事件onListen(elementId, eventType, callback)- 元素事件监听
事件管理
removeAllListeners(elementId)- 移除指定元素的监听器removeAllElementListeners()- 移除所有监听器destroy()- 销毁播放器
🔧 最佳实践
1. 性能优化
// 避免过多的关键帧
// ❌ 不好的做法
const badSchema = {
keyframes: [
{ time: 0, properties: { x: 0 } },
{ time: 10, properties: { x: 1 } },
{ time: 20, properties: { x: 2 } },
// ... 每10ms一个关键帧
],
};
// ✅ 好的做法
const goodSchema = {
keyframes: [
{ time: 0, properties: { x: 0 } },
{ time: 500, properties: { x: 50 } },
{ time: 1000, properties: { x: 100 } },
],
};2. 内存管理
// 在组件卸载时清理播放器
const player = createAnimationPlayer('container', schema);
// 在适当的时候销毁
function cleanup() {
player.destroy(); // 清理所有事件监听器和DOM引用
}
// React 示例
useEffect(() => {
return () => {
cleanup();
};
}, []);3. 错误处理
try {
const player = createAnimationPlayer('container', schema);
player.play();
} catch (error) {
console.error('动画初始化失败:', error);
// 处理错误情况
}⚠️ 注意事项
- 容器元素: 确保容器元素存在且已挂载到DOM
- 唯一ID: 元素ID和关键帧ID必须唯一
- 关键帧关联: 所有关键帧必须关联到存在的元素
- 内存清理: 使用完毕后调用
destroy()方法清理资源 - 时间单位: 所有时间参数使用毫秒为单位
- CSS属性: 支持的CSS属性有限,主要为变换属性
🐛 常见问题
Q: 动画不播放?
A: 检查以下几点:
- 容器元素是否存在
- 动画配置是否正确
- 是否有关键帧数据
- 检查浏览器控制台是否有错误
Q: 模板变量不显示?
A: 确保:
- 数据对象包含对应的属性
- 模板语法正确使用
{{variableName}} - 调用
updateData()后重新渲染
Q: 事件监听器不工作?
A: 检查:
- 元素ID是否正确
- 事件类型名称是否正确
- 元素是否已创建并添加到DOM
📄 许可证
MIT License
🤝 贡献
欢迎提交 Issue 和 Pull Request!
如有疑问,请查看源码注释或提交 Issue。
