@yqg/aminofx-css-kit 1.0.0 → 1.0.1

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,450 @@
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
 
24
- ### IAnimationElement
25
+ ### IJsonSchema
25
26
 
26
- 动画元素配置接口,定义了动画中每个元素的基本信息和样式。
27
+ JSON 数据格式接口,定义动画数据结构。
27
28
 
28
29
  ```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
- };
30
+ interface IJsonSchema {
31
+ /** 动画总时长(毫秒) */
32
+ duration: number;
33
+ /** CSS 动画内容(包含样式和HTML结构) */
34
+ content: string;
41
35
  }
42
36
  ```
43
37
 
44
- ### IPropertieCss
38
+ ### IPlayerOptions
45
39
 
46
- CSS属性接口,定义了动画中常用的CSS变换属性。
40
+ 播放器配置接口,定义创建播放器时的所有可选参数。
47
41
 
48
42
  ```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;
43
+ interface IPlayerOptions {
44
+ /** 弹窗垂直对齐方式 */
45
+ alignItems?: 'center' | 'flex-start' | 'flex-end';
46
+
47
+ /** 直接传入 JSON Schema 数据 */
48
+ jsonSchema?: IJsonSchema;
49
+
50
+ /** 通过 URL 加载 JSON Schema(jsonSchema 优先级更高) */
51
+ jsonUrl?: string;
52
+
53
+ /** 需要预加载的图片列表 */
54
+ preloadImgList?: string[];
55
+
56
+ /** 是否自动循环播放 */
57
+ autoLoop?: boolean;
58
+
59
+ /** 动态数据,用于替换模板变量 */
60
+ dynamicData?: Record<string, string | number | boolean>;
64
61
  }
65
62
  ```
66
63
 
67
- ### IAnimationKeyframe
64
+ ## 🎨 核心类
68
65
 
69
- 动画关键帧接口,定义了某个时间点上元素的属性状态。
66
+ ### AnimationPlayer
70
67
 
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
- ```
68
+ 动画播放器类,负责管理和控制动画的播放。
83
69
 
84
- ### IAnimationSchema
70
+ #### 方法列表
85
71
 
86
- 动画配置模式接口,定义了完整的动画配置。
72
+ | 方法 | 描述 | 参数 | 返回值 |
73
+ |------|------|------|--------|
74
+ | `play()` | 开始播放动画 | - | `Promise<void>` |
75
+ | `ready()` | 等待资源加载完成 | - | `Promise<void>` |
76
+ | `destroy()` | 销毁播放器,清理资源 | - | `void` |
77
+ | `updateSchema(options)` | 更新动画配置并重新初始化 | `options: IPlayerOptions` | `void` |
87
78
 
88
- ```typescript
89
- interface IAnimationSchema {
90
- /** 动画中的所有元素 */
91
- elements: IAnimationElement[];
92
- /** 动画中的所有关键帧 */
93
- keyframes: IAnimationKeyframe[];
94
- /** 全局数据,用于模板渲染 */
95
- data?: Record<string, any>;
96
- }
97
- ```
79
+ ## 🏭 工厂函数
98
80
 
99
- ### IAnimationInfo
81
+ ### createCssAnimationPlayer
100
82
 
101
- 动画信息接口,提供动画的统计信息。
83
+ 创建 CSS 动画播放器的工厂函数。
102
84
 
103
85
  ```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
- }
86
+ function createCssAnimationPlayer(
87
+ containerId: string,
88
+ options: IPlayerOptions
89
+ ): AnimationPlayer;
116
90
  ```
117
91
 
118
- ## 🎭 类型定义
92
+ **参数说明:**
119
93
 
120
- ### EasingFunction
94
+ - `containerId`: 容器元素的 ID
95
+ - `options`: 播放器配置选项
121
96
 
122
- 动画缓动函数类型。
97
+ **返回值:**
123
98
 
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
- ```
99
+ - `AnimationPlayer`: 动画播放器实例
135
100
 
136
- ### AnimationState
137
-
138
- 动画状态类型。
101
+ ## 🎯 快速开始
139
102
 
140
- ```typescript
141
- type AnimationState = 'idle' | 'playing' | 'paused' | 'completed';
103
+ ### 基础示例(使用 jsonUrl)
104
+
105
+ ```html
106
+ <!doctype html>
107
+ <html lang="zh-CN">
108
+ <head>
109
+ <meta charset="UTF-8" />
110
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
111
+ <title>AminoFX CSS Kit Demo</title>
112
+ <script src="https://unpkg.com/aminofx-css-kit/dist/umd/aminofx-css-kit.min.js"></script>
113
+ </head>
114
+ <body>
115
+ <div id="demo-container"></div>
116
+
117
+ <script>
118
+ const player = window.createCssAnimationPlayer('demo-container', {
119
+ jsonUrl: 'https://example.com/animation.json',
120
+ preloadImgList: [
121
+ 'https://example.com/image1.png',
122
+ 'https://example.com/image2.png',
123
+ ],
124
+ alignItems: 'flex-start',
125
+ });
126
+
127
+ player.play();
128
+ </script>
129
+ </body>
130
+ </html>
142
131
  ```
143
132
 
144
- ### ElementEventCallback
145
-
146
- 事件监听器回调函数类型。
133
+ ### 使用 jsonSchema 直接传入
147
134
 
148
135
  ```typescript
149
- type ElementEventCallback = (event: Event, element: HTMLElement) => void;
150
- ```
151
-
152
- ## 🎨 核心类
153
-
154
- ### AnimationPlayer
155
-
156
- 动画播放器主类,负责管理和控制动画的播放。
157
-
158
- #### 构造函数
136
+ import createCssAnimationPlayer from 'aminofx-css-kit';
137
+
138
+ const player = createCssAnimationPlayer('demo-container', {
139
+ jsonSchema: {
140
+ duration: 5720,
141
+ content: `
142
+ <style>
143
+ .animation-box {
144
+ width: 100px;
145
+ height: 100px;
146
+ background: #3b82f6;
147
+ animation: slide 2s ease-in-out;
148
+ }
149
+ @keyframes slide {
150
+ from { transform: translateX(0); }
151
+ to { transform: translateX(200px); }
152
+ }
153
+ </style>
154
+ <div class="animation-box"></div>
155
+ `,
156
+ },
157
+ preloadImgList: [
158
+ 'https://example.com/bg.png',
159
+ ],
160
+ });
159
161
 
160
- ```typescript
161
- constructor(container: HTMLElement, schema: IAnimationSchema)
162
+ // 播放动画
163
+ player.play();
162
164
  ```
163
165
 
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创建动画播放器。
166
+ ### 动态数据替换示例
245
167
 
246
168
  ```typescript
247
- function createAnimationPlayer(
248
- containerId: string,
249
- schema: IAnimationSchema,
250
- ): AnimationPlayer;
251
- ```
169
+ const player = createCssAnimationPlayer('demo-container', {
170
+ jsonSchema: {
171
+ duration: 3000,
172
+ content: `
173
+ <style>
174
+ .title {
175
+ font-size: 24px;
176
+ color: #1f2937;
177
+ animation: fadeIn 1s;
178
+ }
179
+ @keyframes fadeIn {
180
+ from { opacity: 0; }
181
+ to { opacity: 1; }
182
+ }
183
+ </style>
184
+ <div class="title">{{title}}</div>
185
+ `,
186
+ },
187
+ dynamicData: {
188
+ title: '欢迎使用 AminoFX CSS Kit',
189
+ },
190
+ });
252
191
 
253
- ### createAnimationPlayerFromElement
192
+ player.play();
193
+ ```
254
194
 
255
- 直接使用DOM元素创建动画播放器。
195
+ ### 循环播放示例
256
196
 
257
197
  ```typescript
258
- function createAnimationPlayerFromElement(
259
- container: HTMLElement,
260
- schema: IAnimationSchema,
261
- ): AnimationPlayer;
198
+ const player = createCssAnimationPlayer('demo-container', {
199
+ jsonUrl: 'https://example.com/loop-animation.json',
200
+ autoLoop: true, // 启用自动循环
201
+ alignItems: 'center',
202
+ });
203
+
204
+ player.play();
262
205
  ```
263
206
 
264
- ## 🎯 快速开始
207
+ ## 🎪 高级用法
265
208
 
266
- ### 基础示例
209
+ ### 生命周期管理
267
210
 
268
211
  ```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);
212
+ // 创建播放器
213
+ const player = createCssAnimationPlayer('container', {
214
+ jsonUrl: 'https://example.com/animation.json',
215
+ preloadImgList: ['https://example.com/asset1.png'],
216
+ });
308
217
 
309
- // 3. 播放动画
310
- player.play();
311
- ```
218
+ // 等待资源加载完成
219
+ await player.ready();
220
+ console.log('动画资源已准备完成');
312
221
 
313
- ### 模板渲染示例
222
+ // 播放动画
223
+ await player.play();
224
+ console.log('动画开始播放');
314
225
 
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
- };
226
+ // 在适当的时候销毁
227
+ player.destroy();
228
+ console.log('播放器已销毁');
374
229
  ```
375
230
 
376
- ### 事件监听示例
231
+ ### 动态更新动画配置
377
232
 
378
233
  ```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)';
234
+ const player = createCssAnimationPlayer('container', {
235
+ jsonUrl: 'https://example.com/animation1.json',
396
236
  });
397
237
 
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
- });
238
+ // 播放第一个动画
239
+ await player.play();
406
240
 
407
- // 监听播放进度
408
- player.onTimeChange((time) => {
409
- console.log('当前时间:', time);
241
+ // 切换到另一个动画
242
+ player.updateSchema({
243
+ jsonUrl: 'https://example.com/animation2.json',
244
+ autoLoop: true,
410
245
  });
411
246
 
412
- // 监听动画完成
413
- player.onAnimationComplete(() => {
414
- console.log('动画播放完成!');
415
- });
247
+ // 播放新动画
248
+ await player.play();
416
249
  ```
417
250
 
418
- ### 动态数据更新示例
251
+ ### React 集成示例
419
252
 
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
- };
253
+ ```tsx
254
+ import React, { useEffect, useRef, useState } from 'react';
255
+ import createCssAnimationPlayer, { AnimationPlayer } from 'aminofx-css-kit';
456
256
 
457
- const player = createAnimationPlayer('container', schema);
257
+ export const AnimationComponent: React.FC = () => {
258
+ const containerRef = useRef<HTMLDivElement>(null);
259
+ const playerRef = useRef<AnimationPlayer | null>(null);
260
+ const [isReady, setIsReady] = useState(false);
458
261
 
459
- // 动态更新数据
460
- function updateScore(newScore: number) {
461
- player.updateData({ score: newScore });
462
- player.seek(0); // 重新播放动画
463
- player.play();
464
- }
262
+ useEffect(() => {
263
+ if (!containerRef.current) return;
465
264
 
466
- // 使用示例
467
- updateScore(100);
468
- updateScore(250);
469
- ```
265
+ // 创建播放器
266
+ const player = createCssAnimationPlayer('animation-container', {
267
+ jsonUrl: 'https://example.com/animation.json',
268
+ preloadImgList: ['https://example.com/image.png'],
269
+ alignItems: 'center',
270
+ });
470
271
 
471
- ## 🎪 高级用法
272
+ playerRef.current = player;
472
273
 
473
- ### 复杂动画序列
274
+ // 等待资源加载
275
+ player.ready().then(() => {
276
+ setIsReady(true);
277
+ });
474
278
 
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
- ```
279
+ // 清理
280
+ return () => {
281
+ player.destroy();
282
+ playerRef.current = null;
283
+ };
284
+ }, []);
569
285
 
570
- ### 自定义缓动函数
286
+ const handlePlay = () => {
287
+ playerRef.current?.play();
288
+ };
571
289
 
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
- ],
290
+ return (
291
+ <div>
292
+ <div id="animation-container" ref={containerRef} />
293
+ <button onClick={handlePlay} disabled={!isReady}>
294
+ {isReady ? '播放动画' : '加载中...'}
295
+ </button>
296
+ </div>
297
+ );
602
298
  };
603
299
  ```
604
300
 
605
301
  ## 📝 API 参考
606
302
 
607
- ### 动画播放器 API
303
+ ### 播放器实例方法
304
+
305
+ #### play()
306
+
307
+ 开始播放动画。如果动画尚未准备就绪,会自动调用 `ready()` 方法。
608
308
 
609
- #### 播放控制
309
+ ```typescript
310
+ await player.play();
311
+ ```
610
312
 
611
- - `play()` - 播放动画
612
- - `pause()` - 暂停动画
613
- - `stop()` - 停止动画
614
- - `seek(time: number)` - 跳转到指定时间
313
+ #### ready()
615
314
 
616
- #### 状态查询
315
+ 等待所有资源(特别是图片)加载完成。此方法会:
316
+ - 预加载所有指定的图片
317
+ - 确保图片解码完成
318
+ - 返回 Promise,资源准备完成后 resolve
617
319
 
618
- - `getCurrentTime(): number` - 当前播放时间
619
- - `getDuration(): number` - 动画总时长
620
- - `getProgress(): number` - 播放进度 (0-1)
621
- - `getState(): AnimationState` - 当前状态
622
- - `isPlaying(): boolean` - 是否正在播放
320
+ ```typescript
321
+ await player.ready();
322
+ console.log('所有资源已加载完成');
323
+ ```
623
324
 
624
- #### 数据管理
325
+ #### destroy()
625
326
 
626
- - `updateData(data: Record<string, any>)` - 更新动画数据
627
- - `updateSchema(schema: IAnimationSchema)` - 更新动画配置
628
- - `getSchema(): IAnimationSchema` - 获取当前配置
629
- - `getAnimationInfo(): IAnimationInfo` - 获取动画信息
327
+ 销毁播放器,清理所有资源:
328
+ - 清除循环定时器
329
+ - 清空容器内容
330
+ - 重置内部状态
630
331
 
631
- #### 事件监听
332
+ ```typescript
333
+ player.destroy();
334
+ ```
632
335
 
633
- - `onTimeChange(callback)` - 时间变化事件
634
- - `onAnimationComplete(callback)` - 动画完成事件
635
- - `onStateChange(callback)` - 状态变化事件
636
- - `onListen(elementId, eventType, callback)` - 元素事件监听
336
+ #### updateSchema(options)
637
337
 
638
- #### 事件管理
338
+ 更新动画配置并重新初始化。会:
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. 内存管理
671
-
672
- ```typescript
673
- // 在组件卸载时清理播放器
674
- const player = createAnimationPlayer('container', schema);
371
+ ### 2. 资源清理
675
372
 
676
- // 在适当的时候销毁
677
- function cleanup() {
678
- player.destroy(); // 清理所有事件监听器和DOM引用
679
- }
373
+ 在组件卸载或页面离开时,务必销毁播放器:
680
374
 
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: 检查以下几点:
417
+ ### Q: 动画不显示?
715
418
 
716
- - 容器元素是否存在
717
- - 动画配置是否正确
718
- - 是否有关键帧数据
719
- - 检查浏览器控制台是否有错误
419
+ **A:** 检查以下几点:
420
+ - 容器元素是否存在(`document.getElementById(containerId)` 不为 null)
421
+ - JSON Schema 的 `content` 字段是否包含有效的 HTML 和 CSS
422
+ - 检查浏览器控制台是否有错误信息
423
+ - 确认图片 URL 是否可访问
720
424
 
721
- ### Q: 模板变量不显示?
425
+ ### Q: 图片加载失败?
722
426
 
723
- A: 确保:
427
+ **A:**
428
+ - 检查图片 URL 是否正确
429
+ - 确认服务器是否配置了正确的 CORS 头
430
+ - 查看浏览器网络面板,确认图片请求状态
431
+ - 图片加载失败不会阻塞动画播放,但可能影响视觉效果
724
432
 
725
- - 数据对象包含对应的属性
726
- - 模板语法正确使用`{{variableName}}`
727
- - 调用`updateData()`后重新渲染
433
+ ### Q: 循环播放不工作?
728
434
 
729
- ### Q: 事件监听器不工作?
435
+ **A:**
436
+ - 确保 `autoLoop` 设置为 `true`
437
+ - 检查 `jsonSchema.duration` 是否正确设置
438
+ - 循环播放基于定时器实现,确保页面未被挂起
730
439
 
731
- A: 检查:
440
+ ### Q: 如何动态更改动画内容?
732
441
 
733
- - 元素ID是否正确
734
- - 事件类型名称是否正确
735
- - 元素是否已创建并添加到DOM
442
+ **A:** 使用 `updateSchema()` 方法:
736
443
 
737
- ## 📄 许可证
738
-
739
- MIT License
740
-
741
- ## 🤝 贡献
742
-
743
- 欢迎提交 Issue 和 Pull Request!
744
-
745
- ---
746
-
747
- 如有疑问,请查看源码注释或提交 Issue。
444
+ ```typescript
445
+ player.updateSchema({
446
+ jsonSchema: newAnimationData,
447
+ dynamicData: { title: '新标题' },
448
+ });
449
+ player.play();
450
+ ```
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
  }
@@ -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(C([])));_&&_!==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 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(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=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(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&&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){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.1",
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,
@@ -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);