@yqg/aminofx-css-kit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,747 @@
1
+ # 动画播放器 SDK
2
+
3
+ 一个强大、灵活的Web动画播放器SDK,支持基于关键帧的复杂动画制作和播放。
4
+
5
+ ## 🚀 功能特性
6
+
7
+ - **关键帧动画**: 基于时间轴的关键帧动画系统
8
+ - **模板引擎**: 支持`{{variable}}`语法的动态内容渲染
9
+ - **事件系统**: 完整的动画生命周期和元素交互事件支持
10
+ - **CSS变换**: 支持位移、缩放、旋转、透明度等动画属性
11
+ - **缓动函数**: 内置多种缓动函数,包括弹性和弹跳效果
12
+ - **状态管理**: 完整的播放、暂停、停止、跳转控制
13
+ - **自适应时长**: 根据关键帧自动计算动画时长
14
+ - **类型安全**: 完整的TypeScript类型定义
15
+
16
+ ## 📦 安装
17
+
18
+ ```bash
19
+ npm install @yqg-max/click-gate
20
+ ```
21
+
22
+ ## 🏗️ 核心接口
23
+
24
+ ### IAnimationElement
25
+
26
+ 动画元素配置接口,定义了动画中每个元素的基本信息和样式。
27
+
28
+ ```typescript
29
+ interface IAnimationElement {
30
+ /** 元素唯一标识符 */
31
+ id: string;
32
+ /** 元素关联的数据,用于模板渲染 */
33
+ data?: Record<string, any>;
34
+ /** 元素内容配置 */
35
+ content: {
36
+ /** HTML内容模板,支持 {{variable}} 语法 */
37
+ html?: string;
38
+ /** 自定义CSS样式 */
39
+ style?: Record<string, string | number>;
40
+ };
41
+ }
42
+ ```
43
+
44
+ ### IPropertieCss
45
+
46
+ CSS属性接口,定义了动画中常用的CSS变换属性。
47
+
48
+ ```typescript
49
+ interface IPropertieCss {
50
+ /** X轴位置 (px) */
51
+ x: number;
52
+ /** Y轴位置 (px) */
53
+ y: number;
54
+ /** 宽度 (px) */
55
+ width: number;
56
+ /** 高度 (px) */
57
+ height: number;
58
+ /** 旋转角度 (deg) */
59
+ rotation: number;
60
+ /** 透明度 (0-1) */
61
+ opacity: number;
62
+ /** 缩放比例 */
63
+ scale: number;
64
+ }
65
+ ```
66
+
67
+ ### IAnimationKeyframe
68
+
69
+ 动画关键帧接口,定义了某个时间点上元素的属性状态。
70
+
71
+ ```typescript
72
+ interface IAnimationKeyframe {
73
+ /** 关键帧唯一标识符 */
74
+ id: string;
75
+ /** 关联的元素ID */
76
+ elementId: string;
77
+ /** 时间点 (毫秒) */
78
+ time: number;
79
+ /** 该时间点的CSS属性值 */
80
+ properties: Partial<IPropertieCss> & Record<string, any>;
81
+ }
82
+ ```
83
+
84
+ ### IAnimationSchema
85
+
86
+ 动画配置模式接口,定义了完整的动画配置。
87
+
88
+ ```typescript
89
+ interface IAnimationSchema {
90
+ /** 动画中的所有元素 */
91
+ elements: IAnimationElement[];
92
+ /** 动画中的所有关键帧 */
93
+ keyframes: IAnimationKeyframe[];
94
+ /** 全局数据,用于模板渲染 */
95
+ data?: Record<string, any>;
96
+ }
97
+ ```
98
+
99
+ ### IAnimationInfo
100
+
101
+ 动画信息接口,提供动画的统计信息。
102
+
103
+ ```typescript
104
+ interface IAnimationInfo {
105
+ /** 总时长 (毫秒) */
106
+ totalDuration: number;
107
+ /** 最大关键帧时间 */
108
+ maxKeyframeTime: number;
109
+ /** 关键帧数量 */
110
+ keyframeCount: number;
111
+ /** 元素数量 */
112
+ elementCount: number;
113
+ /** 是否自动计算时长 */
114
+ isAutoCalculated: boolean;
115
+ }
116
+ ```
117
+
118
+ ## 🎭 类型定义
119
+
120
+ ### EasingFunction
121
+
122
+ 动画缓动函数类型。
123
+
124
+ ```typescript
125
+ type EasingFunction =
126
+ | 'linear' // 线性
127
+ | 'ease-in' // 缓慢开始
128
+ | 'ease-out' // 缓慢结束
129
+ | 'ease-in-out' // 缓慢开始和结束
130
+ | 'ease-in-cubic' // 三次方缓入
131
+ | 'ease-out-cubic' // 三次方缓出
132
+ | 'bounce-out' // 弹跳结束
133
+ | 'elastic-out'; // 弹性结束
134
+ ```
135
+
136
+ ### AnimationState
137
+
138
+ 动画状态类型。
139
+
140
+ ```typescript
141
+ type AnimationState = 'idle' | 'playing' | 'paused' | 'completed';
142
+ ```
143
+
144
+ ### ElementEventCallback
145
+
146
+ 事件监听器回调函数类型。
147
+
148
+ ```typescript
149
+ type ElementEventCallback = (event: Event, element: HTMLElement) => void;
150
+ ```
151
+
152
+ ## 🎨 核心类
153
+
154
+ ### AnimationPlayer
155
+
156
+ 动画播放器主类,负责管理和控制动画的播放。
157
+
158
+ #### 构造函数
159
+
160
+ ```typescript
161
+ constructor(container: HTMLElement, schema: IAnimationSchema)
162
+ ```
163
+
164
+ #### 播放控制方法
165
+
166
+ | 方法 | 描述 | 参数 | 返回值 |
167
+ | -------------------- | ------------------------ | ---------------------- | ------ |
168
+ | `play()` | 开始播放动画 | - | `void` |
169
+ | `pause()` | 暂停动画 | - | `void` |
170
+ | `stop()` | 停止动画并重置到初始状态 | - | `void` |
171
+ | `seek(time: number)` | 跳转到指定时间 | `time`: 目标时间(毫秒) | `void` |
172
+
173
+ #### 状态查询方法
174
+
175
+ | 方法 | 描述 | 返回值 |
176
+ | -------------------- | ------------------ | ------------------ |
177
+ | `getCurrentTime()` | 获取当前播放时间 | `number` |
178
+ | `getDuration()` | 获取动画总时长 | `number` |
179
+ | `getProgress()` | 获取播放进度(0-1) | `number` |
180
+ | `getState()` | 获取当前状态 | `AnimationState` |
181
+ | `isPlaying()` | 检查是否正在播放 | `boolean` |
182
+ | `getSchema()` | 获取动画配置的副本 | `IAnimationSchema` |
183
+ | `getAnimationInfo()` | 获取动画统计信息 | `IAnimationInfo` |
184
+
185
+ #### 数据更新方法
186
+
187
+ | 方法 | 描述 | 参数 |
188
+ | ------------------------- | ------------ | ----------------------- |
189
+ | `updateData(newData)` | 更新动画数据 | `newData`: 新数据对象 |
190
+ | `updateSchema(newSchema)` | 更新动画配置 | `newSchema`: 新配置对象 |
191
+
192
+ #### 事件监听方法
193
+
194
+ | 方法 | 描述 | 参数 |
195
+ | ------------------------------------------ | ------------ | ------------------------------------------- |
196
+ | `onTimeChange(callback)` | 监听时间变化 | `callback`: (time: number) => void |
197
+ | `onAnimationComplete(callback)` | 监听动画完成 | `callback`: () => void |
198
+ | `onStateChange(callback)` | 监听状态变化 | `callback`: (state: AnimationState) => void |
199
+ | `onListen(elementId, eventType, callback)` | 监听元素事件 | 详见下表 |
200
+
201
+ ##### onListen 参数详情
202
+
203
+ | 参数 | 类型 | 描述 |
204
+ | ----------- | ---------------------- | -------------------------------- |
205
+ | `elementId` | `string` | 元素ID |
206
+ | `eventType` | `string` | 事件类型('click', 'mouseover'等) |
207
+ | `callback` | `ElementEventCallback` | 事件回调函数 |
208
+ | **返回值** | `() => void` | 取消监听的函数 |
209
+
210
+ #### 事件管理方法
211
+
212
+ | 方法 | 描述 | 参数 |
213
+ | ------------------------------- | ---------------------------- | ------------------- |
214
+ | `removeAllListeners(elementId)` | 移除指定元素的所有事件监听器 | `elementId`: 元素ID |
215
+ | `removeAllElementListeners()` | 移除所有事件监听器 | - |
216
+ | `destroy()` | 销毁动画播放器 | - |
217
+
218
+ ### TemplateEngine
219
+
220
+ 模板引擎类,负责解析和渲染模板字符串。
221
+
222
+ #### 静态方法
223
+
224
+ | 方法 | 描述 | 参数 | 返回值 |
225
+ | ------------------------ | -------------- | ------------------------------------------ | -------- |
226
+ | `render(template, data)` | 渲染模板字符串 | `template`: 模板字符串<br>`data`: 渲染数据 | `string` |
227
+
228
+ ### CSSAnimationGenerator
229
+
230
+ CSS动画生成器类,负责生成CSS关键帧动画代码。
231
+
232
+ #### 静态方法
233
+
234
+ | 方法 | 描述 | 参数 | 返回值 |
235
+ | --------------------------------------------------- | ----------------- | ----------------------------------------------------------------- | -------- |
236
+ | `generateKeyframes(elementId, keyframes)` | 生成CSS关键帧动画 | `elementId`: 元素ID<br>`keyframes`: 关键帧数组 | `string` |
237
+ | `generateAnimationCSS(elementId, duration, easing)` | 生成元素动画CSS | `elementId`: 元素ID<br>`duration`: 动画时长<br>`easing`: 缓动函数 | `string` |
238
+ | `easingToCSSFunction(easing)` | 转换缓动函数为CSS | `easing`: 缓动函数名 | `string` |
239
+
240
+ ## 🏭 工厂函数
241
+
242
+ ### createAnimationPlayer
243
+
244
+ 根据容器ID创建动画播放器。
245
+
246
+ ```typescript
247
+ function createAnimationPlayer(
248
+ containerId: string,
249
+ schema: IAnimationSchema,
250
+ ): AnimationPlayer;
251
+ ```
252
+
253
+ ### createAnimationPlayerFromElement
254
+
255
+ 直接使用DOM元素创建动画播放器。
256
+
257
+ ```typescript
258
+ function createAnimationPlayerFromElement(
259
+ container: HTMLElement,
260
+ schema: IAnimationSchema,
261
+ ): AnimationPlayer;
262
+ ```
263
+
264
+ ## 🎯 快速开始
265
+
266
+ ### 基础示例
267
+
268
+ ```typescript
269
+ import { createAnimationPlayer, IAnimationSchema } from '@yqg-max/click-gate';
270
+
271
+ // 1. 定义动画配置
272
+ const schema: IAnimationSchema = {
273
+ elements: [
274
+ {
275
+ id: 'box1',
276
+ content: {
277
+ html: '<div style="width: 100px; height: 100px; background: #3b82f6;"></div>',
278
+ style: {
279
+ borderRadius: '8px',
280
+ },
281
+ },
282
+ },
283
+ ],
284
+ keyframes: [
285
+ {
286
+ id: 'kf1',
287
+ elementId: 'box1',
288
+ time: 0,
289
+ properties: { x: 0, y: 0, opacity: 1, scale: 1 },
290
+ },
291
+ {
292
+ id: 'kf2',
293
+ elementId: 'box1',
294
+ time: 1000,
295
+ properties: { x: 200, y: 100, opacity: 0.5, scale: 1.5 },
296
+ },
297
+ {
298
+ id: 'kf3',
299
+ elementId: 'box1',
300
+ time: 2000,
301
+ properties: { x: 0, y: 0, opacity: 1, scale: 1, rotation: 360 },
302
+ },
303
+ ],
304
+ };
305
+
306
+ // 2. 创建播放器
307
+ const player = createAnimationPlayer('animation-container', schema);
308
+
309
+ // 3. 播放动画
310
+ player.play();
311
+ ```
312
+
313
+ ### 模板渲染示例
314
+
315
+ ```typescript
316
+ const schema: IAnimationSchema = {
317
+ data: {
318
+ title: '欢迎使用动画播放器',
319
+ subtitle: '强大而灵活的动画解决方案',
320
+ },
321
+ elements: [
322
+ {
323
+ id: 'text1',
324
+ data: {
325
+ content: '{{title}}',
326
+ },
327
+ content: {
328
+ html: '<h2>{{content}}</h2>',
329
+ style: {
330
+ color: '#1f2937',
331
+ fontFamily: 'Arial, sans-serif',
332
+ },
333
+ },
334
+ },
335
+ {
336
+ id: 'text2',
337
+ content: {
338
+ html: '<p>{{subtitle}}</p>',
339
+ style: {
340
+ color: '#6b7280',
341
+ },
342
+ },
343
+ },
344
+ ],
345
+ keyframes: [
346
+ // 标题动画
347
+ {
348
+ id: 'title-start',
349
+ elementId: 'text1',
350
+ time: 0,
351
+ properties: { x: -200, opacity: 0 },
352
+ },
353
+ {
354
+ id: 'title-end',
355
+ elementId: 'text1',
356
+ time: 800,
357
+ properties: { x: 0, opacity: 1 },
358
+ },
359
+ // 副标题动画
360
+ {
361
+ id: 'subtitle-start',
362
+ elementId: 'text2',
363
+ time: 400,
364
+ properties: { x: 200, opacity: 0 },
365
+ },
366
+ {
367
+ id: 'subtitle-end',
368
+ elementId: 'text2',
369
+ time: 1200,
370
+ properties: { x: 0, opacity: 1 },
371
+ },
372
+ ],
373
+ };
374
+ ```
375
+
376
+ ### 事件监听示例
377
+
378
+ ```typescript
379
+ // 创建播放器
380
+ const player = createAnimationPlayer('container', schema);
381
+
382
+ // 监听元素点击事件
383
+ const removeClickListener = player.onListen(
384
+ 'button1',
385
+ 'click',
386
+ (event, element) => {
387
+ console.log('按钮被点击了!', element);
388
+ // 可以执行自定义逻辑
389
+ player.seek(1500); // 跳转到1.5秒
390
+ },
391
+ );
392
+
393
+ // 监听元素悬停事件
394
+ player.onListen('image1', 'mouseover', (event, element) => {
395
+ element.style.transform = 'scale(1.1)';
396
+ });
397
+
398
+ player.onListen('image1', 'mouseout', (event, element) => {
399
+ element.style.transform = 'scale(1)';
400
+ });
401
+
402
+ // 监听动画状态变化
403
+ player.onStateChange((state) => {
404
+ console.log('动画状态:', state);
405
+ });
406
+
407
+ // 监听播放进度
408
+ player.onTimeChange((time) => {
409
+ console.log('当前时间:', time);
410
+ });
411
+
412
+ // 监听动画完成
413
+ player.onAnimationComplete(() => {
414
+ console.log('动画播放完成!');
415
+ });
416
+ ```
417
+
418
+ ### 动态数据更新示例
419
+
420
+ ```typescript
421
+ // 创建包含动态数据的动画
422
+ const schema: IAnimationSchema = {
423
+ data: {
424
+ username: 'User',
425
+ score: 0,
426
+ },
427
+ elements: [
428
+ {
429
+ id: 'scoreDisplay',
430
+ content: {
431
+ html: '<div class="score">{{username}}的分数: {{score}}</div>',
432
+ },
433
+ },
434
+ ],
435
+ keyframes: [
436
+ {
437
+ id: 'score-anim',
438
+ elementId: 'scoreDisplay',
439
+ time: 0,
440
+ properties: { scale: 1 },
441
+ },
442
+ {
443
+ id: 'score-bounce',
444
+ elementId: 'scoreDisplay',
445
+ time: 500,
446
+ properties: { scale: 1.2 },
447
+ },
448
+ {
449
+ id: 'score-normal',
450
+ elementId: 'scoreDisplay',
451
+ time: 1000,
452
+ properties: { scale: 1 },
453
+ },
454
+ ],
455
+ };
456
+
457
+ const player = createAnimationPlayer('container', schema);
458
+
459
+ // 动态更新数据
460
+ function updateScore(newScore: number) {
461
+ player.updateData({ score: newScore });
462
+ player.seek(0); // 重新播放动画
463
+ player.play();
464
+ }
465
+
466
+ // 使用示例
467
+ updateScore(100);
468
+ updateScore(250);
469
+ ```
470
+
471
+ ## 🎪 高级用法
472
+
473
+ ### 复杂动画序列
474
+
475
+ ```typescript
476
+ const complexSchema: IAnimationSchema = {
477
+ elements: [
478
+ { id: 'circle', content: { html: '<div class="circle"></div>' } },
479
+ { id: 'square', content: { html: '<div class="square"></div>' } },
480
+ { id: 'triangle', content: { html: '<div class="triangle"></div>' } },
481
+ ],
482
+ keyframes: [
483
+ // 圆形动画序列
484
+ {
485
+ id: 'c1',
486
+ elementId: 'circle',
487
+ time: 0,
488
+ properties: { x: 0, y: 0, opacity: 0 },
489
+ },
490
+ {
491
+ id: 'c2',
492
+ elementId: 'circle',
493
+ time: 500,
494
+ properties: { x: 100, y: 0, opacity: 1 },
495
+ },
496
+ {
497
+ id: 'c3',
498
+ elementId: 'circle',
499
+ time: 1000,
500
+ properties: { x: 100, y: 100, rotation: 180 },
501
+ },
502
+ {
503
+ id: 'c4',
504
+ elementId: 'circle',
505
+ time: 1500,
506
+ properties: { x: 0, y: 100, scale: 1.5 },
507
+ },
508
+ {
509
+ id: 'c5',
510
+ elementId: 'circle',
511
+ time: 2000,
512
+ properties: { x: 0, y: 0, scale: 1, rotation: 360 },
513
+ },
514
+
515
+ // 方形动画序列(延迟启动)
516
+ {
517
+ id: 's1',
518
+ elementId: 'square',
519
+ time: 300,
520
+ properties: { x: 200, y: 0, opacity: 0 },
521
+ },
522
+ {
523
+ id: 's2',
524
+ elementId: 'square',
525
+ time: 800,
526
+ properties: { x: 300, y: 0, opacity: 1 },
527
+ },
528
+ {
529
+ id: 's3',
530
+ elementId: 'square',
531
+ time: 1300,
532
+ properties: { x: 300, y: 100, rotation: 90 },
533
+ },
534
+ {
535
+ id: 's4',
536
+ elementId: 'square',
537
+ time: 1800,
538
+ properties: { x: 200, y: 100, scale: 0.8 },
539
+ },
540
+
541
+ // 三角形动画序列(更晚启动)
542
+ {
543
+ id: 't1',
544
+ elementId: 'triangle',
545
+ time: 600,
546
+ properties: { x: 400, y: 50, opacity: 0 },
547
+ },
548
+ {
549
+ id: 't2',
550
+ elementId: 'triangle',
551
+ time: 1100,
552
+ properties: { x: 450, y: 50, opacity: 1 },
553
+ },
554
+ {
555
+ id: 't3',
556
+ elementId: 'triangle',
557
+ time: 1600,
558
+ properties: { x: 450, y: 100, rotation: 120 },
559
+ },
560
+ {
561
+ id: 't4',
562
+ elementId: 'triangle',
563
+ time: 2100,
564
+ properties: { x: 400, y: 100, scale: 1.2 },
565
+ },
566
+ ],
567
+ };
568
+ ```
569
+
570
+ ### 自定义缓动函数
571
+
572
+ ```typescript
573
+ // 使用不同的缓动函数创建丰富的动画效果
574
+ const bounceSchema: IAnimationSchema = {
575
+ elements: [{ id: 'bouncer', content: { html: '<div class="ball"></div>' } }],
576
+ keyframes: [
577
+ {
578
+ id: 'bounce-start',
579
+ elementId: 'bouncer',
580
+ time: 0,
581
+ properties: { y: 0 },
582
+ },
583
+ {
584
+ id: 'bounce-drop',
585
+ elementId: 'bouncer',
586
+ time: 1000,
587
+ properties: { y: 200 }, // 使用 bounce-out 缓动
588
+ },
589
+ {
590
+ id: 'bounce-up',
591
+ elementId: 'bouncer',
592
+ time: 1500,
593
+ properties: { y: 50 }, // 弹起
594
+ },
595
+ {
596
+ id: 'bounce-settle',
597
+ elementId: 'bouncer',
598
+ time: 2000,
599
+ properties: { y: 200 }, // 最终落地
600
+ },
601
+ ],
602
+ };
603
+ ```
604
+
605
+ ## 📝 API 参考
606
+
607
+ ### 动画播放器 API
608
+
609
+ #### 播放控制
610
+
611
+ - `play()` - 播放动画
612
+ - `pause()` - 暂停动画
613
+ - `stop()` - 停止动画
614
+ - `seek(time: number)` - 跳转到指定时间
615
+
616
+ #### 状态查询
617
+
618
+ - `getCurrentTime(): number` - 当前播放时间
619
+ - `getDuration(): number` - 动画总时长
620
+ - `getProgress(): number` - 播放进度 (0-1)
621
+ - `getState(): AnimationState` - 当前状态
622
+ - `isPlaying(): boolean` - 是否正在播放
623
+
624
+ #### 数据管理
625
+
626
+ - `updateData(data: Record<string, any>)` - 更新动画数据
627
+ - `updateSchema(schema: IAnimationSchema)` - 更新动画配置
628
+ - `getSchema(): IAnimationSchema` - 获取当前配置
629
+ - `getAnimationInfo(): IAnimationInfo` - 获取动画信息
630
+
631
+ #### 事件监听
632
+
633
+ - `onTimeChange(callback)` - 时间变化事件
634
+ - `onAnimationComplete(callback)` - 动画完成事件
635
+ - `onStateChange(callback)` - 状态变化事件
636
+ - `onListen(elementId, eventType, callback)` - 元素事件监听
637
+
638
+ #### 事件管理
639
+
640
+ - `removeAllListeners(elementId)` - 移除指定元素的监听器
641
+ - `removeAllElementListeners()` - 移除所有监听器
642
+ - `destroy()` - 销毁播放器
643
+
644
+ ## 🔧 最佳实践
645
+
646
+ ### 1. 性能优化
647
+
648
+ ```typescript
649
+ // 避免过多的关键帧
650
+ // ❌ 不好的做法
651
+ const badSchema = {
652
+ keyframes: [
653
+ { time: 0, properties: { x: 0 } },
654
+ { time: 10, properties: { x: 1 } },
655
+ { time: 20, properties: { x: 2 } },
656
+ // ... 每10ms一个关键帧
657
+ ],
658
+ };
659
+
660
+ // ✅ 好的做法
661
+ const goodSchema = {
662
+ keyframes: [
663
+ { time: 0, properties: { x: 0 } },
664
+ { time: 500, properties: { x: 50 } },
665
+ { time: 1000, properties: { x: 100 } },
666
+ ],
667
+ };
668
+ ```
669
+
670
+ ### 2. 内存管理
671
+
672
+ ```typescript
673
+ // 在组件卸载时清理播放器
674
+ const player = createAnimationPlayer('container', schema);
675
+
676
+ // 在适当的时候销毁
677
+ function cleanup() {
678
+ player.destroy(); // 清理所有事件监听器和DOM引用
679
+ }
680
+
681
+ // React 示例
682
+ useEffect(() => {
683
+ return () => {
684
+ cleanup();
685
+ };
686
+ }, []);
687
+ ```
688
+
689
+ ### 3. 错误处理
690
+
691
+ ```typescript
692
+ try {
693
+ const player = createAnimationPlayer('container', schema);
694
+ player.play();
695
+ } catch (error) {
696
+ console.error('动画初始化失败:', error);
697
+ // 处理错误情况
698
+ }
699
+ ```
700
+
701
+ ## ⚠️ 注意事项
702
+
703
+ 1. **容器元素**: 确保容器元素存在且已挂载到DOM
704
+ 2. **唯一ID**: 元素ID和关键帧ID必须唯一
705
+ 3. **关键帧关联**: 所有关键帧必须关联到存在的元素
706
+ 4. **内存清理**: 使用完毕后调用`destroy()`方法清理资源
707
+ 5. **时间单位**: 所有时间参数使用毫秒为单位
708
+ 6. **CSS属性**: 支持的CSS属性有限,主要为变换属性
709
+
710
+ ## 🐛 常见问题
711
+
712
+ ### Q: 动画不播放?
713
+
714
+ A: 检查以下几点:
715
+
716
+ - 容器元素是否存在
717
+ - 动画配置是否正确
718
+ - 是否有关键帧数据
719
+ - 检查浏览器控制台是否有错误
720
+
721
+ ### Q: 模板变量不显示?
722
+
723
+ A: 确保:
724
+
725
+ - 数据对象包含对应的属性
726
+ - 模板语法正确使用`{{variableName}}`
727
+ - 调用`updateData()`后重新渲染
728
+
729
+ ### Q: 事件监听器不工作?
730
+
731
+ A: 检查:
732
+
733
+ - 元素ID是否正确
734
+ - 事件类型名称是否正确
735
+ - 元素是否已创建并添加到DOM
736
+
737
+ ## 📄 许可证
738
+
739
+ MIT License
740
+
741
+ ## 🤝 贡献
742
+
743
+ 欢迎提交 Issue 和 Pull Request!
744
+
745
+ ---
746
+
747
+ 如有疑问,请查看源码注释或提交 Issue。