@yqg/aminofx-css-kit 1.0.0 → 1.0.2

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 CHANGED
@@ -1,747 +1,453 @@
1
- # 动画播放器 SDK
1
+ # AminoFX CSS Kit
2
2
 
3
- 一个强大、灵活的Web动画播放器SDK,支持基于关键帧的复杂动画制作和播放。
3
+ 一个轻量级、高性能的 CSS 动画播放器 SDK,专为 Web 动画场景设计。
4
4
 
5
5
  ## 🚀 功能特性
6
6
 
7
- - **关键帧动画**: 基于时间轴的关键帧动画系统
8
- - **模板引擎**: 支持`{{variable}}`语法的动态内容渲染
9
- - **事件系统**: 完整的动画生命周期和元素交互事件支持
10
- - **CSS变换**: 支持位移、缩放、旋转、透明度等动画属性
11
- - **缓动函数**: 内置多种缓动函数,包括弹性和弹跳效果
12
- - **状态管理**: 完整的播放、暂停、停止、跳转控制
13
- - **自适应时长**: 根据关键帧自动计算动画时长
14
- - **类型安全**: 完整的TypeScript类型定义
7
+ - **CSS 动画渲染**: 基于纯 CSS 实现的高性能动画播放
8
+ - **资源预加载**: 智能的图片预加载机制,避免动画卡顿
9
+ - **多种加载方式**: 支持 JSON Schema 直接传入或通过 URL 动态加载
10
+ - **动态数据替换**: 支持模板变量替换,实现数据驱动的动画
11
+ - **循环播放**: 内置自动循环播放功能
12
+ - **灵活布局**: 支持多种垂直对齐方式
13
+ - **生命周期管理**: 完整的初始化、播放、销毁流程
14
+ - **类型安全**: 完整的 TypeScript 类型定义
15
15
 
16
16
  ## 📦 安装
17
17
 
18
18
  ```bash
19
- npm install @yqg-max/click-gate
19
+ npm install aminofx-css-kit
20
20
  ```
21
21
 
22
22
  ## 🏗️ 核心接口
23
23
 
24
- ### IAnimationElement
24
+ ### IJsonSchema
25
25
 
26
- 动画元素配置接口,定义了动画中每个元素的基本信息和样式。
26
+ JSON 数据格式接口,定义动画数据结构。
27
27
 
28
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
- };
29
+ interface IJsonSchema {
30
+ /** 动画总时长(毫秒) */
31
+ duration: number;
32
+ /** CSS 动画内容(包含样式和HTML结构) */
33
+ content: string;
41
34
  }
42
35
  ```
43
36
 
44
- ### IPropertieCss
37
+ ### IPlayerOptions
45
38
 
46
- CSS属性接口,定义了动画中常用的CSS变换属性。
39
+ 播放器配置接口,定义创建播放器时的所有可选参数。
47
40
 
48
41
  ```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
- ```
42
+ interface IPlayerOptions {
43
+ /** 弹窗垂直对齐方式 */
44
+ alignItems?: 'center' | 'flex-start' | 'flex-end';
66
45
 
67
- ### IAnimationKeyframe
46
+ /** 直接传入 JSON Schema 数据 */
47
+ jsonSchema?: IJsonSchema;
68
48
 
69
- 动画关键帧接口,定义了某个时间点上元素的属性状态。
49
+ /** 通过 URL 加载 JSON Schema(jsonSchema 优先级更高) */
50
+ jsonUrl?: string;
70
51
 
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
52
+ /** 需要预加载的图片列表 */
53
+ preloadImgList?: string[];
85
54
 
86
- 动画配置模式接口,定义了完整的动画配置。
55
+ /** 是否自动循环播放 */
56
+ autoLoop?: boolean;
87
57
 
88
- ```typescript
89
- interface IAnimationSchema {
90
- /** 动画中的所有元素 */
91
- elements: IAnimationElement[];
92
- /** 动画中的所有关键帧 */
93
- keyframes: IAnimationKeyframe[];
94
- /** 全局数据,用于模板渲染 */
95
- data?: Record<string, any>;
58
+ /** 动态数据,用于替换模板变量 */
59
+ dynamicData?: Record<string, string | number | boolean>;
96
60
  }
97
61
  ```
98
62
 
99
- ### IAnimationInfo
100
-
101
- 动画信息接口,提供动画的统计信息。
63
+ ## 🎨 核心类
102
64
 
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
- ```
65
+ ### AnimationPlayer
117
66
 
118
- ## 🎭 类型定义
67
+ 动画播放器类,负责管理和控制动画的播放。
119
68
 
120
- ### EasingFunction
69
+ #### 方法列表
121
70
 
122
- 动画缓动函数类型。
71
+ | 方法 | 描述 | 参数 | 返回值 |
72
+ | ----------------------- | ------------------------ | ------------------------- | --------------- |
73
+ | `play()` | 开始播放动画 | - | `Promise<void>` |
74
+ | `ready()` | 等待资源加载完成 | - | `Promise<void>` |
75
+ | `destroy()` | 销毁播放器,清理资源 | - | `void` |
76
+ | `updateSchema(options)` | 更新动画配置并重新初始化 | `options: IPlayerOptions` | `void` |
123
77
 
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
- ```
78
+ ## 🏭 工厂函数
135
79
 
136
- ### AnimationState
80
+ ### createCssAnimationPlayer
137
81
 
138
- 动画状态类型。
82
+ 创建 CSS 动画播放器的工厂函数。
139
83
 
140
84
  ```typescript
141
- type AnimationState = 'idle' | 'playing' | 'paused' | 'completed';
85
+ function createCssAnimationPlayer(
86
+ containerId: string,
87
+ options: IPlayerOptions,
88
+ ): AnimationPlayer;
142
89
  ```
143
90
 
144
- ### ElementEventCallback
91
+ **参数说明:**
145
92
 
146
- 事件监听器回调函数类型。
93
+ - `containerId`: 容器元素的 ID
94
+ - `options`: 播放器配置选项
147
95
 
148
- ```typescript
149
- type ElementEventCallback = (event: Event, element: HTMLElement) => void;
150
- ```
96
+ **返回值:**
151
97
 
152
- ## 🎨 核心类
98
+ - `AnimationPlayer`: 动画播放器实例
153
99
 
154
- ### AnimationPlayer
155
-
156
- 动画播放器主类,负责管理和控制动画的播放。
157
-
158
- #### 构造函数
100
+ ## 🎯 快速开始
159
101
 
160
- ```typescript
161
- constructor(container: HTMLElement, schema: IAnimationSchema)
102
+ ### 基础示例(使用 jsonUrl)
103
+
104
+ ```html
105
+ <!doctype html>
106
+ <html lang="zh-CN">
107
+ <head>
108
+ <meta charset="UTF-8" />
109
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
110
+ <title>AminoFX CSS Kit Demo</title>
111
+ <script src="https://unpkg.com/aminofx-css-kit/dist/umd/aminofx-css-kit.min.js"></script>
112
+ </head>
113
+ <body>
114
+ <div id="demo-container"></div>
115
+
116
+ <script>
117
+ const player = window.createCssAnimationPlayer('demo-container', {
118
+ jsonUrl: 'https://example.com/animation.json',
119
+ preloadImgList: [
120
+ 'https://example.com/image1.png',
121
+ 'https://example.com/image2.png',
122
+ ],
123
+ alignItems: 'flex-start',
124
+ });
125
+
126
+ player.play();
127
+ </script>
128
+ </body>
129
+ </html>
162
130
  ```
163
131
 
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 参数详情
132
+ ### 使用 jsonSchema 直接传入
202
133
 
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
- ## 🏭 工厂函数
134
+ ```typescript
135
+ import createCssAnimationPlayer from 'aminofx-css-kit';
136
+
137
+ const player = createCssAnimationPlayer('demo-container', {
138
+ jsonSchema: {
139
+ duration: 5720,
140
+ content: `
141
+ <style>
142
+ .animation-box {
143
+ width: 100px;
144
+ height: 100px;
145
+ background: #3b82f6;
146
+ animation: slide 2s ease-in-out;
147
+ }
148
+ @keyframes slide {
149
+ from { transform: translateX(0); }
150
+ to { transform: translateX(200px); }
151
+ }
152
+ </style>
153
+ <div class="animation-box"></div>
154
+ `,
155
+ },
156
+ preloadImgList: ['https://example.com/bg.png'],
157
+ });
241
158
 
242
- ### createAnimationPlayer
159
+ // 播放动画
160
+ player.play();
161
+ ```
243
162
 
244
- 根据容器ID创建动画播放器。
163
+ ### 动态数据替换示例
245
164
 
246
165
  ```typescript
247
- function createAnimationPlayer(
248
- containerId: string,
249
- schema: IAnimationSchema,
250
- ): AnimationPlayer;
251
- ```
166
+ const player = createCssAnimationPlayer('demo-container', {
167
+ jsonSchema: {
168
+ duration: 3000,
169
+ content: `
170
+ <style>
171
+ .title {
172
+ font-size: 24px;
173
+ color: #1f2937;
174
+ animation: fadeIn 1s;
175
+ }
176
+ @keyframes fadeIn {
177
+ from { opacity: 0; }
178
+ to { opacity: 1; }
179
+ }
180
+ </style>
181
+ <div class="title">{{title}}</div>
182
+ `,
183
+ },
184
+ dynamicData: {
185
+ title: '欢迎使用 AminoFX CSS Kit',
186
+ },
187
+ });
252
188
 
253
- ### createAnimationPlayerFromElement
189
+ player.play();
190
+ ```
254
191
 
255
- 直接使用DOM元素创建动画播放器。
192
+ ### 循环播放示例
256
193
 
257
194
  ```typescript
258
- function createAnimationPlayerFromElement(
259
- container: HTMLElement,
260
- schema: IAnimationSchema,
261
- ): AnimationPlayer;
195
+ const player = createCssAnimationPlayer('demo-container', {
196
+ jsonUrl: 'https://example.com/loop-animation.json',
197
+ autoLoop: true, // 启用自动循环
198
+ alignItems: 'center',
199
+ });
200
+
201
+ player.play();
262
202
  ```
263
203
 
264
- ## 🎯 快速开始
204
+ ## 🎪 高级用法
265
205
 
266
- ### 基础示例
206
+ ### 生命周期管理
267
207
 
268
208
  ```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);
209
+ // 创建播放器
210
+ const player = createCssAnimationPlayer('container', {
211
+ jsonUrl: 'https://example.com/animation.json',
212
+ preloadImgList: ['https://example.com/asset1.png'],
213
+ });
308
214
 
309
- // 3. 播放动画
310
- player.play();
311
- ```
215
+ // 等待资源加载完成
216
+ await player.ready();
217
+ console.log('动画资源已准备完成');
312
218
 
313
- ### 模板渲染示例
219
+ // 播放动画
220
+ await player.play();
221
+ console.log('动画开始播放');
314
222
 
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
- };
223
+ // 在适当的时候销毁
224
+ player.destroy();
225
+ console.log('播放器已销毁');
374
226
  ```
375
227
 
376
- ### 事件监听示例
228
+ ### 动态更新动画配置
377
229
 
378
230
  ```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)';
231
+ const player = createCssAnimationPlayer('container', {
232
+ jsonUrl: 'https://example.com/animation1.json',
396
233
  });
397
234
 
398
- player.onListen('image1', 'mouseout', (event, element) => {
399
- element.style.transform = 'scale(1)';
400
- });
235
+ // 播放第一个动画
236
+ await player.play();
401
237
 
402
- // 监听动画状态变化
403
- player.onStateChange((state) => {
404
- console.log('动画状态:', state);
238
+ // 切换到另一个动画
239
+ player.updateSchema({
240
+ jsonUrl: 'https://example.com/animation2.json',
241
+ autoLoop: true,
405
242
  });
406
243
 
407
- // 监听播放进度
408
- player.onTimeChange((time) => {
409
- console.log('当前时间:', time);
410
- });
411
-
412
- // 监听动画完成
413
- player.onAnimationComplete(() => {
414
- console.log('动画播放完成!');
415
- });
244
+ // 播放新动画
245
+ await player.play();
416
246
  ```
417
247
 
418
- ### 动态数据更新示例
248
+ ### React 集成示例
419
249
 
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
- };
250
+ ```tsx
251
+ import React, { useEffect, useRef, useState } from 'react';
252
+ import createCssAnimationPlayer, { AnimationPlayer } from 'aminofx-css-kit';
456
253
 
457
- const player = createAnimationPlayer('container', schema);
254
+ export const AnimationComponent: React.FC = () => {
255
+ const containerRef = useRef<HTMLDivElement>(null);
256
+ const playerRef = useRef<AnimationPlayer | null>(null);
257
+ const [isReady, setIsReady] = useState(false);
458
258
 
459
- // 动态更新数据
460
- function updateScore(newScore: number) {
461
- player.updateData({ score: newScore });
462
- player.seek(0); // 重新播放动画
463
- player.play();
464
- }
259
+ useEffect(() => {
260
+ if (!containerRef.current) return;
465
261
 
466
- // 使用示例
467
- updateScore(100);
468
- updateScore(250);
469
- ```
262
+ // 创建播放器
263
+ const player = createCssAnimationPlayer('animation-container', {
264
+ jsonUrl: 'https://example.com/animation.json',
265
+ preloadImgList: ['https://example.com/image.png'],
266
+ alignItems: 'center',
267
+ });
470
268
 
471
- ## 🎪 高级用法
269
+ playerRef.current = player;
472
270
 
473
- ### 复杂动画序列
271
+ // 等待资源加载
272
+ player.ready().then(() => {
273
+ setIsReady(true);
274
+ });
474
275
 
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
- ],
276
+ // 清理
277
+ return () => {
278
+ player.destroy();
279
+ playerRef.current = null;
280
+ };
281
+ }, []);
282
+
283
+ const handlePlay = () => {
284
+ playerRef.current?.play();
285
+ };
286
+
287
+ return (
288
+ <div>
289
+ <div id='animation-container' ref={containerRef} />
290
+ <button onClick={handlePlay} disabled={!isReady}>
291
+ {isReady ? '播放动画' : '加载中...'}
292
+ </button>
293
+ </div>
294
+ );
567
295
  };
568
296
  ```
569
297
 
570
- ### 自定义缓动函数
298
+ ## 📝 API 参考
299
+
300
+ ### 播放器实例方法
301
+
302
+ #### play()
303
+
304
+ 开始播放动画。如果动画尚未准备就绪,会自动调用 `ready()` 方法。
571
305
 
572
306
  ```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
- };
307
+ await player.play();
603
308
  ```
604
309
 
605
- ## 📝 API 参考
310
+ #### ready()
606
311
 
607
- ### 动画播放器 API
312
+ 等待所有资源(特别是图片)加载完成。此方法会:
608
313
 
609
- #### 播放控制
314
+ - 预加载所有指定的图片
315
+ - 确保图片解码完成
316
+ - 返回 Promise,资源准备完成后 resolve
610
317
 
611
- - `play()` - 播放动画
612
- - `pause()` - 暂停动画
613
- - `stop()` - 停止动画
614
- - `seek(time: number)` - 跳转到指定时间
318
+ ```typescript
319
+ await player.ready();
320
+ console.log('所有资源已加载完成');
321
+ ```
615
322
 
616
- #### 状态查询
323
+ #### destroy()
617
324
 
618
- - `getCurrentTime(): number` - 当前播放时间
619
- - `getDuration(): number` - 动画总时长
620
- - `getProgress(): number` - 播放进度 (0-1)
621
- - `getState(): AnimationState` - 当前状态
622
- - `isPlaying(): boolean` - 是否正在播放
325
+ 销毁播放器,清理所有资源:
623
326
 
624
- #### 数据管理
327
+ - 清除循环定时器
328
+ - 清空容器内容
329
+ - 重置内部状态
625
330
 
626
- - `updateData(data: Record<string, any>)` - 更新动画数据
627
- - `updateSchema(schema: IAnimationSchema)` - 更新动画配置
628
- - `getSchema(): IAnimationSchema` - 获取当前配置
629
- - `getAnimationInfo(): IAnimationInfo` - 获取动画信息
331
+ ```typescript
332
+ player.destroy();
333
+ ```
630
334
 
631
- #### 事件监听
335
+ #### updateSchema(options)
632
336
 
633
- - `onTimeChange(callback)` - 时间变化事件
634
- - `onAnimationComplete(callback)` - 动画完成事件
635
- - `onStateChange(callback)` - 状态变化事件
636
- - `onListen(elementId, eventType, callback)` - 元素事件监听
337
+ 更新动画配置并重新初始化。会:
637
338
 
638
- #### 事件管理
339
+ - 清理旧的定时器
340
+ - 重置播放器状态
341
+ - 加载新的动画配置
639
342
 
640
- - `removeAllListeners(elementId)` - 移除指定元素的监听器
641
- - `removeAllElementListeners()` - 移除所有监听器
642
- - `destroy()` - 销毁播放器
343
+ ```typescript
344
+ player.updateSchema({
345
+ jsonUrl: 'https://example.com/new-animation.json',
346
+ autoLoop: true,
347
+ });
348
+ ```
643
349
 
644
350
  ## 🔧 最佳实践
645
351
 
646
- ### 1. 性能优化
352
+ ### 1. 图片预加载
353
+
354
+ 为了获得最佳的动画体验,建议提前声明所有需要的图片:
647
355
 
648
356
  ```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一个关键帧
357
+ const player = createCssAnimationPlayer('container', {
358
+ jsonUrl: 'https://example.com/animation.json',
359
+ preloadImgList: [
360
+ 'https://example.com/bg.png',
361
+ 'https://example.com/icon1.png',
362
+ 'https://example.com/icon2.png',
657
363
  ],
658
- };
364
+ });
659
365
 
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
- };
366
+ // 等待所有图片加载完成
367
+ await player.ready();
368
+ player.play();
668
369
  ```
669
370
 
670
- ### 2. 内存管理
371
+ ### 2. 资源清理
671
372
 
672
- ```typescript
673
- // 在组件卸载时清理播放器
674
- const player = createAnimationPlayer('container', schema);
373
+ 在组件卸载或页面离开时,务必销毁播放器:
675
374
 
676
- // 在适当的时候销毁
677
- function cleanup() {
678
- player.destroy(); // 清理所有事件监听器和DOM引用
679
- }
680
-
681
- // React 示例
375
+ ```typescript
376
+ // React
682
377
  useEffect(() => {
378
+ const player = createCssAnimationPlayer('container', options);
379
+
683
380
  return () => {
684
- cleanup();
381
+ player.destroy(); // 清理资源
685
382
  };
686
383
  }, []);
384
+
385
+ // Vue
386
+ onUnmounted(() => {
387
+ player.value?.destroy();
388
+ });
687
389
  ```
688
390
 
689
- ### 3. 错误处理
391
+ ### 3. 性能优化
690
392
 
691
393
  ```typescript
692
- try {
693
- const player = createAnimationPlayer('container', schema);
694
- player.play();
695
- } catch (error) {
696
- console.error('动画初始化失败:', error);
697
- // 处理错误情况
698
- }
394
+ // ✅ 推荐:使用 jsonSchema 直接传入,避免网络请求
395
+ const player = createCssAnimationPlayer('container', {
396
+ jsonSchema: animationData,
397
+ preloadImgList: imageUrls,
398
+ });
399
+
400
+ // ⚠️ 注意:使用 jsonUrl 会产生额外的网络请求
401
+ const player = createCssAnimationPlayer('container', {
402
+ jsonUrl: 'https://example.com/animation.json',
403
+ });
699
404
  ```
700
405
 
701
406
  ## ⚠️ 注意事项
702
407
 
703
- 1. **容器元素**: 确保容器元素存在且已挂载到DOM
704
- 2. **唯一ID**: 元素ID和关键帧ID必须唯一
705
- 3. **关键帧关联**: 所有关键帧必须关联到存在的元素
706
- 4. **内存清理**: 使用完毕后调用`destroy()`方法清理资源
707
- 5. **时间单位**: 所有时间参数使用毫秒为单位
708
- 6. **CSS属性**: 支持的CSS属性有限,主要为变换属性
408
+ 1. **容器元素**:确保容器元素在调用 `createCssAnimationPlayer` 时已存在于 DOM
409
+ 2. **资源路径**:预加载图片列表中的 URL 必须是完整的 HTTP/HTTPS 地址
410
+ 3. **优先级**:当同时传入 `jsonSchema` 和 `jsonUrl` 时,`jsonSchema` 优先级更高
411
+ 4. **循环播放**:启用 `autoLoop` 时,确保提供了 `duration` 属性
412
+ 5. **内存管理**:使用完毕后务必调用 `destroy()` 方法清理资源
413
+ 6. **CORS**:通过 URL 加载的资源需要正确配置 CORS 策略
709
414
 
710
415
  ## 🐛 常见问题
711
416
 
712
- ### Q: 动画不播放?
713
-
714
- A: 检查以下几点:
715
-
716
- - 容器元素是否存在
717
- - 动画配置是否正确
718
- - 是否有关键帧数据
719
- - 检查浏览器控制台是否有错误
720
-
721
- ### Q: 模板变量不显示?
417
+ ### Q: 动画不显示?
722
418
 
723
- A: 确保:
419
+ **A:** 检查以下几点:
724
420
 
725
- - 数据对象包含对应的属性
726
- - 模板语法正确使用`{{variableName}}`
727
- - 调用`updateData()`后重新渲染
421
+ - 容器元素是否存在(`document.getElementById(containerId)` 不为 null)
422
+ - JSON Schema 的 `content` 字段是否包含有效的 HTML 和 CSS
423
+ - 检查浏览器控制台是否有错误信息
424
+ - 确认图片 URL 是否可访问
728
425
 
729
- ### Q: 事件监听器不工作?
426
+ ### Q: 图片加载失败?
730
427
 
731
- A: 检查:
428
+ **A:**
732
429
 
733
- - 元素ID是否正确
734
- - 事件类型名称是否正确
735
- - 元素是否已创建并添加到DOM
430
+ - 检查图片 URL 是否正确
431
+ - 确认服务器是否配置了正确的 CORS 头
432
+ - 查看浏览器网络面板,确认图片请求状态
433
+ - 图片加载失败不会阻塞动画播放,但可能影响视觉效果
736
434
 
737
- ## 📄 许可证
435
+ ### Q: 循环播放不工作?
738
436
 
739
- MIT License
437
+ **A:**
740
438
 
741
- ## 🤝 贡献
439
+ - 确保 `autoLoop` 设置为 `true`
440
+ - 检查 `jsonSchema.duration` 是否正确设置
441
+ - 循环播放基于定时器实现,确保页面未被挂起
742
442
 
743
- 欢迎提交 Issue 和 Pull Request!
443
+ ### Q: 如何动态更改动画内容?
744
444
 
745
- ---
445
+ **A:** 使用 `updateSchema()` 方法:
746
446
 
747
- 如有疑问,请查看源码注释或提交 Issue。
447
+ ```typescript
448
+ player.updateSchema({
449
+ jsonSchema: newAnimationData,
450
+ dynamicData: { title: '新标题' },
451
+ });
452
+ player.play();
453
+ ```
package/dist/esm/index.js CHANGED
@@ -120,36 +120,46 @@ var AnimationPlayer = /*#__PURE__*/function () {
120
120
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
121
121
  while (1) switch (_context2.prev = _context2.next) {
122
122
  case 0:
123
+ Object.assign(this.container.style, {
124
+ display: 'none',
125
+ width: '100vw',
126
+ height: '100vh',
127
+ overflow: 'hidden',
128
+ alignItems: this.options.alignItems || 'center',
129
+ justifyContent: 'center',
130
+ backgroundColor: 'rgba(0, 0, 0, 0.85)',
131
+ backdropFilter: 'blur(10px)'
132
+ });
123
133
  if (!this.options.jsonSchema) {
124
- _context2.next = 4;
134
+ _context2.next = 5;
125
135
  break;
126
136
  }
127
137
  this.container.innerHTML = this.replacePlaceholders(this.options.jsonSchema.content);
128
- _context2.next = 16;
138
+ _context2.next = 17;
129
139
  break;
130
- case 4:
140
+ case 5:
131
141
  if (!((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.jsonUrl)) {
132
- _context2.next = 15;
142
+ _context2.next = 16;
133
143
  break;
134
144
  }
135
- _context2.next = 7;
145
+ _context2.next = 8;
136
146
  return fetch((_this$options2 = this.options) === null || _this$options2 === void 0 ? void 0 : _this$options2.jsonUrl);
137
- case 7:
147
+ case 8:
138
148
  response = _context2.sent;
139
- _context2.next = 10;
149
+ _context2.next = 11;
140
150
  return response.json();
141
- case 10:
151
+ case 11:
142
152
  data = _context2.sent;
143
153
  this.options.jsonSchema = data;
144
154
  this.container.innerHTML = this.replacePlaceholders(((_this$options$jsonSch = this.options.jsonSchema) === null || _this$options$jsonSch === void 0 ? void 0 : _this$options$jsonSch.content) || '');
145
- _context2.next = 16;
155
+ _context2.next = 17;
146
156
  break;
147
- case 15:
148
- throw new Error('没有提供jsonSchema或jsonUrl');
149
157
  case 16:
150
- _context2.next = 18;
158
+ throw new Error('没有提供jsonSchema或jsonUrl');
159
+ case 17:
160
+ _context2.next = 19;
151
161
  return this.ready();
152
- case 18:
162
+ case 19:
153
163
  case "end":
154
164
  return _context2.stop();
155
165
  }
@@ -189,7 +199,7 @@ var AnimationPlayer = /*#__PURE__*/function () {
189
199
  _this3 = this,
190
200
  _this$options$jsonSch3,
191
201
  _this$options$jsonSch4;
192
- if (!this.options.autoLoop || !((_this$options$jsonSch2 = this.options.jsonSchema) !== null && _this$options$jsonSch2 !== void 0 && _this$options$jsonSch2.duration)) {
202
+ if (!this.options.autoLoop || !Number((_this$options$jsonSch2 = this.options.jsonSchema) === null || _this$options$jsonSch2 === void 0 ? void 0 : _this$options$jsonSch2.duration)) {
193
203
  return;
194
204
  }
195
205
 
@@ -207,7 +217,7 @@ var AnimationPlayer = /*#__PURE__*/function () {
207
217
  _this3.loopTimerId = null;
208
218
  _this3.play();
209
219
  }, 100);
210
- }, (_this$options$jsonSch3 = this.options.jsonSchema) === null || _this$options$jsonSch3 === void 0 ? void 0 : _this$options$jsonSch3.duration);
220
+ }, Number((_this$options$jsonSch3 = this.options.jsonSchema) === null || _this$options$jsonSch3 === void 0 ? void 0 : _this$options$jsonSch3.duration));
211
221
  console.log("aminofx: \uD83D\uDD04 \u542F\u52A8\u5FAA\u73AF\u5B9A\u65F6\u5668\uFF0C\u65F6\u957F: ".concat((_this$options$jsonSch4 = this.options.jsonSchema) === null || _this$options$jsonSch4 === void 0 ? void 0 : _this$options$jsonSch4.duration, "ms"));
212
222
  }
213
223
  }, {
@@ -324,16 +334,7 @@ var AnimationPlayer = /*#__PURE__*/function () {
324
334
  }, {
325
335
  key: "updateSchema",
326
336
  value: function updateSchema(options) {
327
- // 清理旧的循环定时器
328
- if (this.loopTimerId !== null) {
329
- clearTimeout(this.loopTimerId);
330
- this.loopTimerId = null;
331
- console.log('aminofx: 🧹 更新Schema时清理循环定时器');
332
- }
333
-
334
- // 重置状态
335
- this.isReady = false;
336
- this.readyPromise = null;
337
+ this.destroy();
337
338
 
338
339
  // 更新配置并重新初始化
339
340
  this.options = options;
@@ -350,16 +351,6 @@ function createCssAnimationPlayer(containerId, options) {
350
351
 
351
352
  // 固定比例画布容器,通过设置container适配不同比例机型
352
353
  var canvasContainer = document.createElement('div');
353
- Object.assign(canvasContainer.style, {
354
- display: 'none',
355
- width: '100vw',
356
- height: '100vh',
357
- overflow: 'hidden',
358
- alignItems: options.alignItems || 'center',
359
- justifyContent: 'center',
360
- backgroundColor: 'rgba(0, 0, 0, 0.85)',
361
- backdropFilter: 'blur(10px)'
362
- });
363
354
  var instance = new AnimationPlayer(canvasContainer, options);
364
355
  container.appendChild(canvasContainer);
365
356
  return instance;
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports["@yqg/aminofx-css-kit"]=e():t["@yqg/aminofx-css-kit"]=e()}(self,(function(){return function(){var t={506:function(){},365:function(t){function e(t,e,r,n,o,i,a){try{var s=t[i](a),c=s.value}catch(t){return void r(t)}s.done?e(c):Promise.resolve(c).then(n,o)}t.exports=function(t){return function(){var r=this,n=arguments;return new Promise((function(o,i){var a=t.apply(r,n);function s(t){e(a,o,i,s,c,"next",t)}function c(t){e(a,o,i,s,c,"throw",t)}s(void 0)}))}},t.exports.__esModule=!0,t.exports.default=t.exports},156:function(t){t.exports=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},t.exports.__esModule=!0,t.exports.default=t.exports},499:function(t,e,r){var n=r(714);function o(t,e){for(var r=0;r<e.length;r++){var o=e[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,n(o.key),o)}}t.exports=function(t,e,r){return e&&o(t.prototype,e),r&&o(t,r),Object.defineProperty(t,"prototype",{writable:!1}),t},t.exports.__esModule=!0,t.exports.default=t.exports},173:function(t,e,r){var n=r(714);t.exports=function(t,e,r){return(e=n(e))in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t},t.exports.__esModule=!0,t.exports.default=t.exports},298:function(t,e,r){var n=r(241).default;function o(){"use strict";t.exports=o=function(){return r},t.exports.__esModule=!0,t.exports.default=t.exports;var e,r={},i=Object.prototype,a=i.hasOwnProperty,s=Object.defineProperty||function(t,e,r){t[e]=r.value},c="function"==typeof Symbol?Symbol:{},u=c.iterator||"@@iterator",l=c.asyncIterator||"@@asyncIterator",f=c.toStringTag||"@@toStringTag";function p(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{p({},"")}catch(e){p=function(t,e,r){return t[e]=r}}function h(t,e,r,n){var o=e&&e.prototype instanceof g?e:g,i=Object.create(o.prototype),a=new M(n||[]);return s(i,"_invoke",{value:S(t,r,a)}),i}function d(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}r.wrap=h;var y="suspendedStart",v="executing",m="completed",x={};function g(){}function w(){}function b(){}var P={};p(P,u,(function(){return this}));var j=Object.getPrototypeOf,_=j&&j(j(C([])));_&&_!==i&&a.call(_,u)&&(P=_);var k=b.prototype=g.prototype=Object.create(P);function L(t){["next","throw","return"].forEach((function(e){p(t,e,(function(t){return this._invoke(e,t)}))}))}function T(t,e){function r(o,i,s,c){var u=d(t[o],t,i);if("throw"!==u.type){var l=u.arg,f=l.value;return f&&"object"==n(f)&&a.call(f,"__await")?e.resolve(f.__await).then((function(t){r("next",t,s,c)}),(function(t){r("throw",t,s,c)})):e.resolve(f).then((function(t){l.value=t,s(l)}),(function(t){return r("throw",t,s,c)}))}c(u.arg)}var o;s(this,"_invoke",{value:function(t,n){function i(){return new e((function(e,o){r(t,n,e,o)}))}return o=o?o.then(i,i):i()}})}function S(t,r,n){var o=y;return function(i,a){if(o===v)throw new Error("Generator is already running");if(o===m){if("throw"===i)throw a;return{value:e,done:!0}}for(n.method=i,n.arg=a;;){var s=n.delegate;if(s){var c=E(s,n);if(c){if(c===x)continue;return c}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===y)throw o=m,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=v;var u=d(t,r,n);if("normal"===u.type){if(o=n.done?m:"suspendedYield",u.arg===x)continue;return{value:u.arg,done:n.done}}"throw"===u.type&&(o=m,n.method="throw",n.arg=u.arg)}}}function E(t,r){var n=r.method,o=t.iterator[n];if(o===e)return r.delegate=null,"throw"===n&&t.iterator.return&&(r.method="return",r.arg=e,E(t,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),x;var i=d(o,t.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,x;var a=i.arg;return a?a.done?(r[t.resultName]=a.value,r.next=t.nextLoc,"return"!==r.method&&(r.method="next",r.arg=e),r.delegate=null,x):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,x)}function O(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function I(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function M(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(O,this),this.reset(!0)}function C(t){if(t||""===t){var r=t[u];if(r)return r.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var o=-1,i=function r(){for(;++o<t.length;)if(a.call(t,o))return r.value=t[o],r.done=!1,r;return r.value=e,r.done=!0,r};return i.next=i}}throw new TypeError(n(t)+" is not iterable")}return w.prototype=b,s(k,"constructor",{value:b,configurable:!0}),s(b,"constructor",{value:w,configurable:!0}),w.displayName=p(b,f,"GeneratorFunction"),r.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===w||"GeneratorFunction"===(e.displayName||e.name))},r.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,b):(t.__proto__=b,p(t,f,"GeneratorFunction")),t.prototype=Object.create(k),t},r.awrap=function(t){return{__await:t}},L(T.prototype),p(T.prototype,l,(function(){return this})),r.AsyncIterator=T,r.async=function(t,e,n,o,i){void 0===i&&(i=Promise);var a=new T(h(t,e,n,o),i);return r.isGeneratorFunction(e)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},L(k),p(k,f,"Generator"),p(k,u,(function(){return this})),p(k,"toString",(function(){return"[object Generator]"})),r.keys=function(t){var e=Object(t),r=[];for(var n in e)r.push(n);return r.reverse(),function t(){for(;r.length;){var n=r.pop();if(n in e)return t.value=n,t.done=!1,t}return t.done=!0,t}},r.values=C,M.prototype={constructor:M,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(I),!t)for(var r in this)"t"===r.charAt(0)&&a.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=e)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var r=this;function n(n,o){return s.type="throw",s.arg=t,r.next=n,o&&(r.method="next",r.arg=e),!!o}for(var o=this.tryEntries.length-1;o>=0;--o){var i=this.tryEntries[o],s=i.completion;if("root"===i.tryLoc)return n("end");if(i.tryLoc<=this.prev){var c=a.call(i,"catchLoc"),u=a.call(i,"finallyLoc");if(c&&u){if(this.prev<i.catchLoc)return n(i.catchLoc,!0);if(this.prev<i.finallyLoc)return n(i.finallyLoc)}else if(c){if(this.prev<i.catchLoc)return n(i.catchLoc,!0)}else{if(!u)throw new Error("try statement without catch or finally");if(this.prev<i.finallyLoc)return n(i.finallyLoc)}}}},abrupt:function(t,e){for(var r=this.tryEntries.length-1;r>=0;--r){var n=this.tryEntries[r];if(n.tryLoc<=this.prev&&a.call(n,"finallyLoc")&&this.prev<n.finallyLoc){var o=n;break}}o&&("break"===t||"continue"===t)&&o.tryLoc<=e&&e<=o.finallyLoc&&(o=null);var i=o?o.completion:{};return i.type=t,i.arg=e,o?(this.method="next",this.next=o.finallyLoc,x):this.complete(i)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),x},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),I(r),x}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;I(r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,n){return this.delegate={iterator:C(t),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=e),x}},r}t.exports=o,t.exports.__esModule=!0,t.exports.default=t.exports},569:function(t,e,r){var n=r(241).default;t.exports=function(t,e){if("object"!=n(t)||!t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var o=r.call(t,e||"default");if("object"!=n(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)},t.exports.__esModule=!0,t.exports.default=t.exports},714:function(t,e,r){var n=r(241).default,o=r(569);t.exports=function(t){var e=o(t,"string");return"symbol"==n(e)?e:String(e)},t.exports.__esModule=!0,t.exports.default=t.exports},241:function(t){function e(r){return t.exports=e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t.exports.__esModule=!0,t.exports.default=t.exports,e(r)}t.exports=e,t.exports.__esModule=!0,t.exports.default=t.exports}},e={};function r(n){var o=e[n];if(void 0!==o)return o.exports;var i=e[n]={exports:{}};return t[n](i,i.exports,r),i.exports}r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,{a:e}),e},r.d=function(t,e){for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};return function(){"use strict";r.r(n),r.d(n,{AnimationPlayer:function(){return v}});var t=r(298),e=r.n(t),o=r(365),i=r.n(o),a=r(156),s=r.n(a),c=r(499),u=r.n(c),l=r(173),f=r.n(l),p=r(506),h={};for(var d in p)["default","AnimationPlayer"].indexOf(d)<0&&(h[d]=function(t){return p[t]}.bind(0,d));r.d(n,h);var y=function(){function t(){s()(this,t)}var r;return u()(t,null,[{key:"loadImages",value:(r=i()(e()().mark((function t(r){var n,o=this;return e()().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(Array.isArray(r)&&0!==r.length){t.next=2;break}return t.abrupt("return",Promise.resolve());case 2:return n=r.map((function(t,e){if(!t.startsWith("http"))return Promise.resolve();if(o.imageCache.has(t))return console.log("aminofx: ✅ 图片 ".concat(e+1," 已缓存: ").concat(t)),Promise.resolve();if(o.loadingQueue.has(t))return o.loadingQueue.get(t);var r=new Promise((function(r){var n=new Image;n.onload=function(){o.imageCache.set(t,!0),o.loadingQueue.delete(t),console.log("aminofx: ✅ 图片 ".concat(e+1," 加载成功: ").concat(t)),"function"==typeof n.decode?n.decode().then((function(){console.log("aminofx: 🎨 图片 ".concat(e+1," 解码完成: ").concat(t)),r()})).catch((function(){console.log("aminofx: ⚠️ 图片 ".concat(e+1," decode失败,使用fallback: ").concat(t)),r()})):(console.log("aminofx: 📱 图片 ".concat(e+1," 使用兼容模式: ").concat(t)),r())},n.src=t,n.onerror=function(){o.loadingQueue.delete(t),console.error("aminofx: ❌ 图片 ".concat(e+1," 加载失败: ").concat(t)),r()}}));return o.loadingQueue.set(t,r),r})),t.prev=3,t.next=6,Promise.all(n);case 6:console.log("aminofx: 🎉 所有图片资源加载完成"),t.next=12;break;case 9:t.prev=9,t.t0=t.catch(3),console.error("aminofx: ❌ 图片加载过程中出现错误:",t.t0);case 12:case"end":return t.stop()}}),t,null,[[3,9]])}))),function(t){return r.apply(this,arguments)})}]),t}();f()(y,"imageCache",new Map),f()(y,"loadingQueue",new Map);var v=function(){function t(e,r){s()(this,t),f()(this,"container",void 0),f()(this,"options",void 0),f()(this,"isReady",!1),f()(this,"readyPromise",null),f()(this,"loopTimerId",null),this.container=e,this.options=r,this.init()}var r,n,o;return u()(t,[{key:"init",value:(o=i()(e()().mark((function t(){var r,n,o,i,a;return e()().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(!this.options.jsonSchema){t.next=4;break}this.container.innerHTML=this.replacePlaceholders(this.options.jsonSchema.content),t.next=16;break;case 4:if(null===(r=this.options)||void 0===r||!r.jsonUrl){t.next=15;break}return t.next=7,fetch(null===(n=this.options)||void 0===n?void 0:n.jsonUrl);case 7:return i=t.sent,t.next=10,i.json();case 10:a=t.sent,this.options.jsonSchema=a,this.container.innerHTML=this.replacePlaceholders((null===(o=this.options.jsonSchema)||void 0===o?void 0:o.content)||""),t.next=16;break;case 15:throw new Error("没有提供jsonSchema或jsonUrl");case 16:return t.next=18,this.ready();case 18:case"end":return t.stop()}}),t,this)}))),function(){return o.apply(this,arguments)})},{key:"replacePlaceholders",value:function(t){var e=this;return this.options.dynamicData&&t?t.replace(/\{\{(\w+)\}\}|\$\{(\w+)\}/g,(function(t,r,n){var o,i=r||n;return void 0!==(null===(o=e.options.dynamicData)||void 0===o?void 0:o[i])?String(e.options.dynamicData[i]):t})):t}},{key:"handleLoop",value:function(){var t,e,r,n=this;this.options.autoLoop&&null!==(t=this.options.jsonSchema)&&void 0!==t&&t.duration&&(null!==this.loopTimerId&&(clearTimeout(this.loopTimerId),this.loopTimerId=null,console.log("aminofx: 🧹 清理旧的循环定时器")),this.loopTimerId=window.setTimeout((function(){n.container.style.display="none",window.setTimeout((function(){n.loopTimerId=null,n.play()}),100)}),null===(e=this.options.jsonSchema)||void 0===e?void 0:e.duration),console.log("aminofx: 🔄 启动循环定时器,时长: ".concat(null===(r=this.options.jsonSchema)||void 0===r?void 0:r.duration,"ms")))}},{key:"ready",value:(n=i()(e()().mark((function t(){var r=this;return e()().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(!this.isReady){t.next=3;break}return console.log("aminofx: ✅ 动画已准备就绪,直接返回"),t.abrupt("return",Promise.resolve());case 3:if(!this.readyPromise){t.next=6;break}return console.log("aminofx: ⏳ 正在准备中,等待现有Promise..."),t.abrupt("return",this.readyPromise);case 6:return this.readyPromise=new Promise(function(){var t=i()(e()().mark((function t(n){return e()().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.prev=0,t.next=3,y.loadImages(r.options.preloadImgList||[]);case 3:r.isReady=!0,console.log("aminofx: 🎉 动画准备完成,可以开始播放"),t.next=10;break;case 7:t.prev=7,t.t0=t.catch(0),console.error("aminofx: ❌ 动画准备失败:",t.t0);case 10:n();case 11:case"end":return t.stop()}}),t,null,[[0,7]])})));return function(e){return t.apply(this,arguments)}}()),t.abrupt("return",this.readyPromise);case 8:case"end":return t.stop()}}),t,this)}))),function(){return n.apply(this,arguments)})},{key:"play",value:(r=i()(e()().mark((function t(){return e()().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(this.isReady){t.next=4;break}return console.warn("aminofx: ⚠️ 动画尚未准备就绪,自动调用ready()..."),t.next=4,this.ready();case 4:this.container.style.display="flex",this.options.autoLoop&&null===this.loopTimerId&&this.handleLoop();case 6:case"end":return t.stop()}}),t,this)}))),function(){return r.apply(this,arguments)})},{key:"destroy",value:function(){null!==this.loopTimerId&&(clearTimeout(this.loopTimerId),this.loopTimerId=null,console.log("aminofx: 🧹 销毁时清理循环定时器")),this.container.innerHTML="",this.isReady=!1,this.readyPromise=null,console.log("aminofx: 🗑️ AnimationPlayer 已销毁")}},{key:"updateSchema",value:function(t){null!==this.loopTimerId&&(clearTimeout(this.loopTimerId),this.loopTimerId=null,console.log("aminofx: 🧹 更新Schema时清理循环定时器")),this.isReady=!1,this.readyPromise=null,this.options=t,this.init()}}]),t}();function m(t,e){var r=document.getElementById(t);if(!r)throw new Error('Container with id "'.concat(t,'" not found'));var n=document.createElement("div");Object.assign(n.style,{display:"none",width:"100vw",height:"100vh",overflow:"hidden",alignItems:e.alignItems||"center",justifyContent:"center",backgroundColor:"rgba(0, 0, 0, 0.85)",backdropFilter:"blur(10px)"});var o=new v(n,e);return r.appendChild(n),o}n.default=m,window.createCssAnimationPlayer=m}(),n}()}));
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports["@yqg/aminofx-css-kit"]=e():t["@yqg/aminofx-css-kit"]=e()}(self,(function(){return function(){var t={506:function(){},365:function(t){function e(t,e,r,n,o,i,a){try{var s=t[i](a),c=s.value}catch(t){return void r(t)}s.done?e(c):Promise.resolve(c).then(n,o)}t.exports=function(t){return function(){var r=this,n=arguments;return new Promise((function(o,i){var a=t.apply(r,n);function s(t){e(a,o,i,s,c,"next",t)}function c(t){e(a,o,i,s,c,"throw",t)}s(void 0)}))}},t.exports.__esModule=!0,t.exports.default=t.exports},156:function(t){t.exports=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},t.exports.__esModule=!0,t.exports.default=t.exports},499:function(t,e,r){var n=r(714);function o(t,e){for(var r=0;r<e.length;r++){var o=e[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,n(o.key),o)}}t.exports=function(t,e,r){return e&&o(t.prototype,e),r&&o(t,r),Object.defineProperty(t,"prototype",{writable:!1}),t},t.exports.__esModule=!0,t.exports.default=t.exports},173:function(t,e,r){var n=r(714);t.exports=function(t,e,r){return(e=n(e))in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t},t.exports.__esModule=!0,t.exports.default=t.exports},298:function(t,e,r){var n=r(241).default;function o(){"use strict";t.exports=o=function(){return r},t.exports.__esModule=!0,t.exports.default=t.exports;var e,r={},i=Object.prototype,a=i.hasOwnProperty,s=Object.defineProperty||function(t,e,r){t[e]=r.value},c="function"==typeof Symbol?Symbol:{},u=c.iterator||"@@iterator",l=c.asyncIterator||"@@asyncIterator",f=c.toStringTag||"@@toStringTag";function p(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{p({},"")}catch(e){p=function(t,e,r){return t[e]=r}}function h(t,e,r,n){var o=e&&e.prototype instanceof g?e:g,i=Object.create(o.prototype),a=new M(n||[]);return s(i,"_invoke",{value:S(t,r,a)}),i}function d(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}r.wrap=h;var y="suspendedStart",v="executing",m="completed",x={};function g(){}function w(){}function b(){}var j={};p(j,u,(function(){return this}));var P=Object.getPrototypeOf,_=P&&P(P(N([])));_&&_!==i&&a.call(_,u)&&(j=_);var k=b.prototype=g.prototype=Object.create(j);function L(t){["next","throw","return"].forEach((function(e){p(t,e,(function(t){return this._invoke(e,t)}))}))}function E(t,e){function r(o,i,s,c){var u=d(t[o],t,i);if("throw"!==u.type){var l=u.arg,f=l.value;return f&&"object"==n(f)&&a.call(f,"__await")?e.resolve(f.__await).then((function(t){r("next",t,s,c)}),(function(t){r("throw",t,s,c)})):e.resolve(f).then((function(t){l.value=t,s(l)}),(function(t){return r("throw",t,s,c)}))}c(u.arg)}var o;s(this,"_invoke",{value:function(t,n){function i(){return new e((function(e,o){r(t,n,e,o)}))}return o=o?o.then(i,i):i()}})}function S(t,r,n){var o=y;return function(i,a){if(o===v)throw new Error("Generator is already running");if(o===m){if("throw"===i)throw a;return{value:e,done:!0}}for(n.method=i,n.arg=a;;){var s=n.delegate;if(s){var c=T(s,n);if(c){if(c===x)continue;return c}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===y)throw o=m,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=v;var u=d(t,r,n);if("normal"===u.type){if(o=n.done?m:"suspendedYield",u.arg===x)continue;return{value:u.arg,done:n.done}}"throw"===u.type&&(o=m,n.method="throw",n.arg=u.arg)}}}function T(t,r){var n=r.method,o=t.iterator[n];if(o===e)return r.delegate=null,"throw"===n&&t.iterator.return&&(r.method="return",r.arg=e,T(t,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),x;var i=d(o,t.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,x;var a=i.arg;return a?a.done?(r[t.resultName]=a.value,r.next=t.nextLoc,"return"!==r.method&&(r.method="next",r.arg=e),r.delegate=null,x):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,x)}function O(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function I(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function M(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(O,this),this.reset(!0)}function N(t){if(t||""===t){var r=t[u];if(r)return r.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var o=-1,i=function r(){for(;++o<t.length;)if(a.call(t,o))return r.value=t[o],r.done=!1,r;return r.value=e,r.done=!0,r};return i.next=i}}throw new TypeError(n(t)+" is not iterable")}return w.prototype=b,s(k,"constructor",{value:b,configurable:!0}),s(b,"constructor",{value:w,configurable:!0}),w.displayName=p(b,f,"GeneratorFunction"),r.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===w||"GeneratorFunction"===(e.displayName||e.name))},r.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,b):(t.__proto__=b,p(t,f,"GeneratorFunction")),t.prototype=Object.create(k),t},r.awrap=function(t){return{__await:t}},L(E.prototype),p(E.prototype,l,(function(){return this})),r.AsyncIterator=E,r.async=function(t,e,n,o,i){void 0===i&&(i=Promise);var a=new E(h(t,e,n,o),i);return r.isGeneratorFunction(e)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},L(k),p(k,f,"Generator"),p(k,u,(function(){return this})),p(k,"toString",(function(){return"[object Generator]"})),r.keys=function(t){var e=Object(t),r=[];for(var n in e)r.push(n);return r.reverse(),function t(){for(;r.length;){var n=r.pop();if(n in e)return t.value=n,t.done=!1,t}return t.done=!0,t}},r.values=N,M.prototype={constructor:M,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(I),!t)for(var r in this)"t"===r.charAt(0)&&a.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=e)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var r=this;function n(n,o){return s.type="throw",s.arg=t,r.next=n,o&&(r.method="next",r.arg=e),!!o}for(var o=this.tryEntries.length-1;o>=0;--o){var i=this.tryEntries[o],s=i.completion;if("root"===i.tryLoc)return n("end");if(i.tryLoc<=this.prev){var c=a.call(i,"catchLoc"),u=a.call(i,"finallyLoc");if(c&&u){if(this.prev<i.catchLoc)return n(i.catchLoc,!0);if(this.prev<i.finallyLoc)return n(i.finallyLoc)}else if(c){if(this.prev<i.catchLoc)return n(i.catchLoc,!0)}else{if(!u)throw new Error("try statement without catch or finally");if(this.prev<i.finallyLoc)return n(i.finallyLoc)}}}},abrupt:function(t,e){for(var r=this.tryEntries.length-1;r>=0;--r){var n=this.tryEntries[r];if(n.tryLoc<=this.prev&&a.call(n,"finallyLoc")&&this.prev<n.finallyLoc){var o=n;break}}o&&("break"===t||"continue"===t)&&o.tryLoc<=e&&e<=o.finallyLoc&&(o=null);var i=o?o.completion:{};return i.type=t,i.arg=e,o?(this.method="next",this.next=o.finallyLoc,x):this.complete(i)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),x},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),I(r),x}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var r=this.tryEntries[e];if(r.tryLoc===t){var n=r.completion;if("throw"===n.type){var o=n.arg;I(r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,n){return this.delegate={iterator:N(t),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=e),x}},r}t.exports=o,t.exports.__esModule=!0,t.exports.default=t.exports},569:function(t,e,r){var n=r(241).default;t.exports=function(t,e){if("object"!=n(t)||!t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var o=r.call(t,e||"default");if("object"!=n(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)},t.exports.__esModule=!0,t.exports.default=t.exports},714:function(t,e,r){var n=r(241).default,o=r(569);t.exports=function(t){var e=o(t,"string");return"symbol"==n(e)?e:String(e)},t.exports.__esModule=!0,t.exports.default=t.exports},241:function(t){function e(r){return t.exports=e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},t.exports.__esModule=!0,t.exports.default=t.exports,e(r)}t.exports=e,t.exports.__esModule=!0,t.exports.default=t.exports}},e={};function r(n){var o=e[n];if(void 0!==o)return o.exports;var i=e[n]={exports:{}};return t[n](i,i.exports,r),i.exports}r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,{a:e}),e},r.d=function(t,e){for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};return function(){"use strict";r.r(n),r.d(n,{AnimationPlayer:function(){return v}});var t=r(298),e=r.n(t),o=r(365),i=r.n(o),a=r(156),s=r.n(a),c=r(499),u=r.n(c),l=r(173),f=r.n(l),p=r(506),h={};for(var d in p)["default","AnimationPlayer"].indexOf(d)<0&&(h[d]=function(t){return p[t]}.bind(0,d));r.d(n,h);var y=function(){function t(){s()(this,t)}var r;return u()(t,null,[{key:"loadImages",value:(r=i()(e()().mark((function t(r){var n,o=this;return e()().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(Array.isArray(r)&&0!==r.length){t.next=2;break}return t.abrupt("return",Promise.resolve());case 2:return n=r.map((function(t,e){if(!t.startsWith("http"))return Promise.resolve();if(o.imageCache.has(t))return console.log("aminofx: ✅ 图片 ".concat(e+1," 已缓存: ").concat(t)),Promise.resolve();if(o.loadingQueue.has(t))return o.loadingQueue.get(t);var r=new Promise((function(r){var n=new Image;n.onload=function(){o.imageCache.set(t,!0),o.loadingQueue.delete(t),console.log("aminofx: ✅ 图片 ".concat(e+1," 加载成功: ").concat(t)),"function"==typeof n.decode?n.decode().then((function(){console.log("aminofx: 🎨 图片 ".concat(e+1," 解码完成: ").concat(t)),r()})).catch((function(){console.log("aminofx: ⚠️ 图片 ".concat(e+1," decode失败,使用fallback: ").concat(t)),r()})):(console.log("aminofx: 📱 图片 ".concat(e+1," 使用兼容模式: ").concat(t)),r())},n.src=t,n.onerror=function(){o.loadingQueue.delete(t),console.error("aminofx: ❌ 图片 ".concat(e+1," 加载失败: ").concat(t)),r()}}));return o.loadingQueue.set(t,r),r})),t.prev=3,t.next=6,Promise.all(n);case 6:console.log("aminofx: 🎉 所有图片资源加载完成"),t.next=12;break;case 9:t.prev=9,t.t0=t.catch(3),console.error("aminofx: ❌ 图片加载过程中出现错误:",t.t0);case 12:case"end":return t.stop()}}),t,null,[[3,9]])}))),function(t){return r.apply(this,arguments)})}]),t}();f()(y,"imageCache",new Map),f()(y,"loadingQueue",new Map);var v=function(){function t(e,r){s()(this,t),f()(this,"container",void 0),f()(this,"options",void 0),f()(this,"isReady",!1),f()(this,"readyPromise",null),f()(this,"loopTimerId",null),this.container=e,this.options=r,this.init()}var r,n,o;return u()(t,[{key:"init",value:(o=i()(e()().mark((function t(){var r,n,o,i,a;return e()().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(Object.assign(this.container.style,{display:"none",width:"100vw",height:"100vh",overflow:"hidden",alignItems:this.options.alignItems||"center",justifyContent:"center",backgroundColor:"rgba(0, 0, 0, 0.85)",backdropFilter:"blur(10px)"}),!this.options.jsonSchema){t.next=5;break}this.container.innerHTML=this.replacePlaceholders(this.options.jsonSchema.content),t.next=17;break;case 5:if(null===(r=this.options)||void 0===r||!r.jsonUrl){t.next=16;break}return t.next=8,fetch(null===(n=this.options)||void 0===n?void 0:n.jsonUrl);case 8:return i=t.sent,t.next=11,i.json();case 11:a=t.sent,this.options.jsonSchema=a,this.container.innerHTML=this.replacePlaceholders((null===(o=this.options.jsonSchema)||void 0===o?void 0:o.content)||""),t.next=17;break;case 16:throw new Error("没有提供jsonSchema或jsonUrl");case 17:return t.next=19,this.ready();case 19:case"end":return t.stop()}}),t,this)}))),function(){return o.apply(this,arguments)})},{key:"replacePlaceholders",value:function(t){var e=this;return this.options.dynamicData&&t?t.replace(/\{\{(\w+)\}\}|\$\{(\w+)\}/g,(function(t,r,n){var o,i=r||n;return void 0!==(null===(o=e.options.dynamicData)||void 0===o?void 0:o[i])?String(e.options.dynamicData[i]):t})):t}},{key:"handleLoop",value:function(){var t,e,r,n=this;this.options.autoLoop&&Number(null===(t=this.options.jsonSchema)||void 0===t?void 0:t.duration)&&(null!==this.loopTimerId&&(clearTimeout(this.loopTimerId),this.loopTimerId=null,console.log("aminofx: 🧹 清理旧的循环定时器")),this.loopTimerId=window.setTimeout((function(){n.container.style.display="none",window.setTimeout((function(){n.loopTimerId=null,n.play()}),100)}),Number(null===(e=this.options.jsonSchema)||void 0===e?void 0:e.duration)),console.log("aminofx: 🔄 启动循环定时器,时长: ".concat(null===(r=this.options.jsonSchema)||void 0===r?void 0:r.duration,"ms")))}},{key:"ready",value:(n=i()(e()().mark((function t(){var r=this;return e()().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(!this.isReady){t.next=3;break}return console.log("aminofx: ✅ 动画已准备就绪,直接返回"),t.abrupt("return",Promise.resolve());case 3:if(!this.readyPromise){t.next=6;break}return console.log("aminofx: ⏳ 正在准备中,等待现有Promise..."),t.abrupt("return",this.readyPromise);case 6:return this.readyPromise=new Promise(function(){var t=i()(e()().mark((function t(n){return e()().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.prev=0,t.next=3,y.loadImages(r.options.preloadImgList||[]);case 3:r.isReady=!0,console.log("aminofx: 🎉 动画准备完成,可以开始播放"),t.next=10;break;case 7:t.prev=7,t.t0=t.catch(0),console.error("aminofx: ❌ 动画准备失败:",t.t0);case 10:n();case 11:case"end":return t.stop()}}),t,null,[[0,7]])})));return function(e){return t.apply(this,arguments)}}()),t.abrupt("return",this.readyPromise);case 8:case"end":return t.stop()}}),t,this)}))),function(){return n.apply(this,arguments)})},{key:"play",value:(r=i()(e()().mark((function t(){return e()().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(this.isReady){t.next=4;break}return console.warn("aminofx: ⚠️ 动画尚未准备就绪,自动调用ready()..."),t.next=4,this.ready();case 4:this.container.style.display="flex",this.options.autoLoop&&null===this.loopTimerId&&this.handleLoop();case 6:case"end":return t.stop()}}),t,this)}))),function(){return r.apply(this,arguments)})},{key:"destroy",value:function(){null!==this.loopTimerId&&(clearTimeout(this.loopTimerId),this.loopTimerId=null,console.log("aminofx: 🧹 销毁时清理循环定时器")),this.container.innerHTML="",this.isReady=!1,this.readyPromise=null,console.log("aminofx: 🗑️ AnimationPlayer 已销毁")}},{key:"updateSchema",value:function(t){this.destroy(),this.options=t,this.init()}}]),t}();function m(t,e){var r=document.getElementById(t);if(!r)throw new Error('Container with id "'.concat(t,'" not found'));var n=document.createElement("div"),o=new v(n,e);return r.appendChild(n),o}n.default=m,window.createCssAnimationPlayer=m}(),n}()}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yqg/aminofx-css-kit",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "YQG AminoFX CSS animation kit - Core animation utilities and effects",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
package/src/index.ts CHANGED
@@ -99,6 +99,17 @@ class AnimationPlayer {
99
99
  }
100
100
 
101
101
  private async init(): Promise<void> {
102
+ Object.assign(this.container.style, {
103
+ display: 'none',
104
+ width: '100vw',
105
+ height: '100vh',
106
+ overflow: 'hidden',
107
+ alignItems: this.options.alignItems || 'center',
108
+ justifyContent: 'center',
109
+ backgroundColor: 'rgba(0, 0, 0, 0.85)',
110
+ backdropFilter: 'blur(10px)',
111
+ });
112
+
102
113
  if (this.options.jsonSchema) {
103
114
  this.container.innerHTML = this.replacePlaceholders(
104
115
  this.options.jsonSchema.content,
@@ -142,7 +153,7 @@ class AnimationPlayer {
142
153
  }
143
154
 
144
155
  private handleLoop() {
145
- if (!this.options.autoLoop || !this.options.jsonSchema?.duration) {
156
+ if (!this.options.autoLoop || !Number(this.options.jsonSchema?.duration)) {
146
157
  return;
147
158
  }
148
159
 
@@ -160,7 +171,7 @@ class AnimationPlayer {
160
171
  this.loopTimerId = null;
161
172
  this.play();
162
173
  }, 100);
163
- }, this.options.jsonSchema?.duration);
174
+ }, Number(this.options.jsonSchema?.duration));
164
175
 
165
176
  console.log(
166
177
  `aminofx: 🔄 启动循环定时器,时长: ${this.options.jsonSchema?.duration}ms`,
@@ -223,16 +234,7 @@ class AnimationPlayer {
223
234
  }
224
235
 
225
236
  updateSchema(options: IPlayerOptions): void {
226
- // 清理旧的循环定时器
227
- if (this.loopTimerId !== null) {
228
- clearTimeout(this.loopTimerId);
229
- this.loopTimerId = null;
230
- console.log('aminofx: 🧹 更新Schema时清理循环定时器');
231
- }
232
-
233
- // 重置状态
234
- this.isReady = false;
235
- this.readyPromise = null;
237
+ this.destroy();
236
238
 
237
239
  // 更新配置并重新初始化
238
240
  this.options = options;
@@ -252,17 +254,6 @@ function createCssAnimationPlayer(
252
254
  // 固定比例画布容器,通过设置container适配不同比例机型
253
255
  const canvasContainer = document.createElement('div');
254
256
 
255
- Object.assign(canvasContainer.style, {
256
- display: 'none',
257
- width: '100vw',
258
- height: '100vh',
259
- overflow: 'hidden',
260
- alignItems: options.alignItems || 'center',
261
- justifyContent: 'center',
262
- backgroundColor: 'rgba(0, 0, 0, 0.85)',
263
- backdropFilter: 'blur(10px)',
264
- });
265
-
266
257
  const instance = new AnimationPlayer(canvasContainer, options);
267
258
 
268
259
  container.appendChild(canvasContainer);