canvasframework 0.5.16 → 0.5.18

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.
Files changed (112) hide show
  1. package/dist/canvasframework.js +2 -0
  2. package/dist/canvasframework.js.LICENSE.txt +1 -0
  3. package/package.json +18 -17
  4. package/components/Accordion.js +0 -265
  5. package/components/AndroidDatePickerDialog.js +0 -406
  6. package/components/AppBar.js +0 -398
  7. package/components/AudioPlayer.js +0 -611
  8. package/components/Avatar.js +0 -202
  9. package/components/Banner.js +0 -342
  10. package/components/BottomNavigationBar.js +0 -433
  11. package/components/BottomSheet.js +0 -234
  12. package/components/Button.js +0 -360
  13. package/components/Camera.js +0 -644
  14. package/components/Card.js +0 -193
  15. package/components/Chart.js +0 -700
  16. package/components/Checkbox.js +0 -166
  17. package/components/Chip.js +0 -212
  18. package/components/CircularProgress.js +0 -327
  19. package/components/ContextMenu.js +0 -116
  20. package/components/DatePicker.js +0 -298
  21. package/components/Dialog.js +0 -337
  22. package/components/Divider.js +0 -125
  23. package/components/Drawer.js +0 -276
  24. package/components/FAB.js +0 -270
  25. package/components/FileUpload.js +0 -315
  26. package/components/FloatedCamera.js +0 -644
  27. package/components/IOSDatePickerWheel.js +0 -430
  28. package/components/ImageCarousel.js +0 -219
  29. package/components/ImageComponent.js +0 -223
  30. package/components/Input.js +0 -831
  31. package/components/InputDatalist.js +0 -723
  32. package/components/InputTags.js +0 -624
  33. package/components/List.js +0 -95
  34. package/components/ListItem.js +0 -269
  35. package/components/Modal.js +0 -364
  36. package/components/MorphingFAB.js +0 -428
  37. package/components/MultiSelectDialog.js +0 -206
  38. package/components/NumberInput.js +0 -271
  39. package/components/PasswordInput.js +0 -462
  40. package/components/ProgressBar.js +0 -88
  41. package/components/QRCodeReader.js +0 -539
  42. package/components/RadioButton.js +0 -151
  43. package/components/SearchInput.js +0 -315
  44. package/components/SegmentedControl.js +0 -357
  45. package/components/Select.js +0 -199
  46. package/components/SelectDialog.js +0 -255
  47. package/components/Slider.js +0 -113
  48. package/components/SliverAppBar.js +0 -139
  49. package/components/Snackbar.js +0 -243
  50. package/components/SpeedDialFAB.js +0 -397
  51. package/components/Stepper.js +0 -281
  52. package/components/SwipeableListItem.js +0 -327
  53. package/components/Switch.js +0 -147
  54. package/components/Table.js +0 -492
  55. package/components/Tabs.js +0 -423
  56. package/components/Text.js +0 -141
  57. package/components/TextField.js +0 -151
  58. package/components/TimePicker.js +0 -934
  59. package/components/Toast.js +0 -236
  60. package/components/TreeView.js +0 -420
  61. package/components/Video.js +0 -397
  62. package/components/View.js +0 -140
  63. package/components/VirtualList.js +0 -120
  64. package/core/CanvasFramework.js +0 -3034
  65. package/core/Component.js +0 -243
  66. package/core/ThemeManager.js +0 -358
  67. package/core/UIBuilder.js +0 -267
  68. package/core/WebGLCanvasAdapter.js +0 -782
  69. package/features/Column.js +0 -43
  70. package/features/Grid.js +0 -47
  71. package/features/LayoutComponent.js +0 -43
  72. package/features/OpenStreetMap.js +0 -310
  73. package/features/Positioned.js +0 -33
  74. package/features/PullToRefresh.js +0 -328
  75. package/features/Row.js +0 -40
  76. package/features/SignaturePad.js +0 -257
  77. package/features/Skeleton.js +0 -193
  78. package/features/Stack.js +0 -21
  79. package/index.js +0 -119
  80. package/manager/AccessibilityManager.js +0 -107
  81. package/manager/ErrorHandler.js +0 -59
  82. package/manager/FeatureFlags.js +0 -60
  83. package/manager/MemoryManager.js +0 -107
  84. package/manager/PerformanceMonitor.js +0 -84
  85. package/manager/SecurityManager.js +0 -54
  86. package/utils/AnimationEngine.js +0 -734
  87. package/utils/CryptoManager.js +0 -303
  88. package/utils/DataStore.js +0 -403
  89. package/utils/DevTools.js +0 -1618
  90. package/utils/DevToolsConsole.js +0 -201
  91. package/utils/EventBus.js +0 -407
  92. package/utils/FetchClient.js +0 -74
  93. package/utils/FirebaseAuth.js +0 -653
  94. package/utils/FirebaseCore.js +0 -246
  95. package/utils/FirebaseFirestore.js +0 -581
  96. package/utils/FirebaseFunctions.js +0 -97
  97. package/utils/FirebaseRealtimeDB.js +0 -498
  98. package/utils/FirebaseStorage.js +0 -612
  99. package/utils/FormValidator.js +0 -355
  100. package/utils/GeoLocationService.js +0 -62
  101. package/utils/I18n.js +0 -207
  102. package/utils/IndexedDBManager.js +0 -273
  103. package/utils/InspectionOverlay.js +0 -308
  104. package/utils/NotificationManager.js +0 -60
  105. package/utils/OfflineSyncManager.js +0 -342
  106. package/utils/PayPalPayment.js +0 -678
  107. package/utils/QueryBuilder.js +0 -478
  108. package/utils/SafeArea.js +0 -64
  109. package/utils/SecureStorage.js +0 -289
  110. package/utils/StateManager.js +0 -207
  111. package/utils/StripePayment.js +0 -552
  112. package/utils/WebSocketClient.js +0 -66
@@ -1,734 +0,0 @@
1
- /**
2
- * Moteur d'animation pour composants Canvas
3
- * Permet d'animer n'importe quelle propriété d'un composant sans le modifier
4
- * @class
5
- * @property {Map} animations - Liste des animations actives
6
- * @property {boolean} isRunning - Indique si le moteur tourne
7
- */
8
- class AnimationEngine {
9
- constructor() {
10
- this.animations = new Map();
11
- this.isRunning = false;
12
- this.animationFrameId = null;
13
-
14
- // Batching
15
- this.batchQueue = [];
16
- this.batchScheduled = false;
17
-
18
- // Worker pour les calculs d'animation
19
- this.worker = null;
20
- this.workerEnabled = true;
21
- this.initWorker();
22
-
23
- // OffscreenCanvas cache
24
- this.offscreenCache = new Map();
25
- }
26
-
27
- /**
28
- * Initialise le Web Worker pour les animations
29
- * @private
30
- */
31
- initWorker() {
32
- if (!window.Worker) {
33
- this.workerEnabled = false;
34
- console.warn('Web Workers non supportés, fallback sur le thread principal');
35
- return;
36
- }
37
-
38
- // Créer le worker inline
39
- const workerCode = `
40
- // Fonctions d'easing dans le Worker
41
- const easings = {
42
- linear: t => t,
43
- easeInQuad: t => t * t,
44
- easeOutQuad: t => t * (2 - t),
45
- easeInOutQuad: t => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
46
- easeInCubic: t => t * t * t,
47
- easeOutCubic: t => (--t) * t * t + 1,
48
- easeInOutCubic: t => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
49
- easeInQuart: t => t * t * t * t,
50
- easeOutQuart: t => 1 - (--t) * t * t * t,
51
- easeInOutQuart: t => t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t,
52
- easeInElastic: t => {
53
- const c4 = (2 * Math.PI) / 3;
54
- return t === 0 ? 0 : t === 1 ? 1 : -Math.pow(2, 10 * t - 10) * Math.sin((t * 10 - 10.75) * c4);
55
- },
56
- easeOutElastic: t => {
57
- const c4 = (2 * Math.PI) / 3;
58
- return t === 0 ? 0 : t === 1 ? 1 : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
59
- },
60
- easeOutBounce: t => {
61
- const n1 = 7.5625;
62
- const d1 = 2.75;
63
- if (t < 1 / d1) return n1 * t * t;
64
- else if (t < 2 / d1) return n1 * (t -= 1.5 / d1) * t + 0.75;
65
- else if (t < 2.5 / d1) return n1 * (t -= 2.25 / d1) * t + 0.9375;
66
- else return n1 * (t -= 2.625 / d1) * t + 0.984375;
67
- }
68
- };
69
-
70
- // Calculer les valeurs d'animation
71
- self.onmessage = function(e) {
72
- const { type, data } = e.data;
73
-
74
- if (type === 'CALCULATE_BATCH') {
75
- const { animations, currentTime } = data;
76
- const results = [];
77
-
78
- for (let anim of animations) {
79
- // Gérer le délai
80
- if (anim.isDelaying) {
81
- if (!anim.delayStartTime) {
82
- anim.delayStartTime = currentTime;
83
- }
84
-
85
- if (currentTime - anim.delayStartTime >= anim.delay) {
86
- anim.isDelaying = false;
87
- anim.startTime = currentTime;
88
- } else {
89
- results.push({ id: anim.id, status: 'delaying', animation: anim });
90
- continue;
91
- }
92
- }
93
-
94
- // Initialiser le temps de départ
95
- if (!anim.startTime) {
96
- anim.startTime = currentTime;
97
- }
98
-
99
- // Calculer la progression
100
- const elapsed = currentTime - anim.startTime;
101
- let progress = Math.min(elapsed / anim.duration, 1);
102
-
103
- // Appliquer l'easing
104
- const easingFunc = easings[anim.easing] || easings.linear;
105
- const easedProgress = easingFunc(progress);
106
-
107
- // Inverser si yoyo
108
- const actualProgress = anim.isReversed ? 1 - easedProgress : easedProgress;
109
-
110
- // Calculer les nouvelles valeurs
111
- const values = {};
112
- for (let prop in anim.to) {
113
- const from = anim.from[prop];
114
- const to = anim.to[prop];
115
- values[prop] = from + (to - from) * actualProgress;
116
- }
117
-
118
- // Déterminer le statut
119
- let status = 'running';
120
- let newState = { ...anim };
121
-
122
- if (progress >= 1) {
123
- if (anim.yoyo && !anim.isReversed) {
124
- status = 'yoyo';
125
- newState.isReversed = true;
126
- newState.startTime = currentTime;
127
- } else if (anim.loop) {
128
- status = 'loop';
129
- newState.startTime = currentTime;
130
- newState.isReversed = false;
131
- } else {
132
- status = 'complete';
133
- }
134
- }
135
-
136
- results.push({
137
- id: anim.id,
138
- status,
139
- values,
140
- actualProgress,
141
- animation: newState
142
- });
143
- }
144
-
145
- self.postMessage({ type: 'BATCH_RESULT', results });
146
- }
147
- };
148
- `;
149
-
150
- const blob = new Blob([workerCode], { type: 'application/javascript' });
151
- const workerUrl = URL.createObjectURL(blob);
152
-
153
- try {
154
- this.worker = new Worker(workerUrl);
155
-
156
- this.worker.onmessage = (e) => {
157
- if (e.data.type === 'BATCH_RESULT') {
158
- this.applyBatchResults(e.data.results);
159
- }
160
- };
161
-
162
- this.worker.onerror = (error) => {
163
- console.error('Erreur Worker:', error);
164
- this.workerEnabled = false;
165
- };
166
- } catch (error) {
167
- console.error('Impossible de créer le Worker:', error);
168
- this.workerEnabled = false;
169
- }
170
- }
171
-
172
- /**
173
- * Applique les résultats calculés par le Worker
174
- * @private
175
- */
176
- applyBatchResults(results) {
177
- const toDelete = [];
178
-
179
- for (let result of results) {
180
- const anim = this.animations.get(result.id);
181
- if (!anim) continue;
182
-
183
- if (result.status === 'delaying') {
184
- // Mettre à jour l'état de délai
185
- Object.assign(anim, result.animation);
186
- continue;
187
- }
188
-
189
- // Mettre à jour les propriétés du composant
190
- if (result.values) {
191
- for (let prop in result.values) {
192
- anim.component[prop] = result.values[prop];
193
- }
194
- }
195
-
196
- // Callback onUpdate
197
- if (anim.onUpdate) {
198
- anim.onUpdate(result.actualProgress);
199
- }
200
-
201
- // Gérer les états
202
- if (result.status === 'yoyo' || result.status === 'loop') {
203
- Object.assign(anim, result.animation);
204
- } else if (result.status === 'complete') {
205
- if (anim.onComplete) {
206
- anim.onComplete();
207
- }
208
- toDelete.push(result.id);
209
- }
210
- }
211
-
212
- // Nettoyer les animations terminées
213
- toDelete.forEach(id => this.stop(id));
214
- }
215
-
216
- /**
217
- * Crée un OffscreenCanvas pour pré-rendre un composant
218
- * @param {string} cacheKey - Clé de cache
219
- * @param {number} width - Largeur
220
- * @param {number} height - Hauteur
221
- * @param {Function} renderFn - Fonction de rendu
222
- */
223
- createOffscreenCache(cacheKey, width, height, renderFn) {
224
- if (!window.OffscreenCanvas) {
225
- console.warn('OffscreenCanvas non supporté');
226
- return null;
227
- }
228
-
229
- const offscreen = new OffscreenCanvas(width, height);
230
- const ctx = offscreen.getContext('2d');
231
-
232
- renderFn(ctx);
233
-
234
- this.offscreenCache.set(cacheKey, offscreen);
235
- return offscreen;
236
- }
237
-
238
- /**
239
- * Récupère un OffscreenCanvas du cache
240
- * @param {string} cacheKey - Clé de cache
241
- */
242
- getOffscreenCache(cacheKey) {
243
- return this.offscreenCache.get(cacheKey);
244
- }
245
-
246
- /**
247
- * Nettoie le cache OffscreenCanvas
248
- * @param {string} cacheKey - Clé de cache (optionnel)
249
- */
250
- clearOffscreenCache(cacheKey = null) {
251
- if (cacheKey) {
252
- this.offscreenCache.delete(cacheKey);
253
- } else {
254
- this.offscreenCache.clear();
255
- }
256
- }
257
-
258
- /**
259
- * Anime une propriété d'un composant
260
- * @param {Component} component - Composant à animer
261
- * @param {Object} options - Options d'animation
262
- * @param {Object} options.from - Valeurs de départ {x: 0, y: 0, ...}
263
- * @param {Object} options.to - Valeurs d'arrivée {x: 100, y: 200, ...}
264
- * @param {number} options.duration - Durée en ms (défaut: 300)
265
- * @param {string} options.easing - Fonction d'easing (défaut: 'easeInOutQuad')
266
- * @param {number} options.delay - Délai avant démarrage en ms (défaut: 0)
267
- * @param {Function} options.onUpdate - Callback à chaque frame
268
- * @param {Function} options.onComplete - Callback à la fin
269
- * @param {boolean} options.loop - Boucler l'animation (défaut: false)
270
- * @param {boolean} options.yoyo - Retour inverse (défaut: false)
271
- * @returns {string} ID de l'animation
272
- */
273
- animate(component, options = {}) {
274
- const animationId = this.generateId();
275
-
276
- const animation = {
277
- id: animationId,
278
- component,
279
- from: options.from || {},
280
- to: options.to || {},
281
- duration: options.duration || 300,
282
- easing: options.easing || 'easeInOutQuad',
283
- delay: options.delay || 0,
284
- onUpdate: options.onUpdate,
285
- onComplete: options.onComplete,
286
- loop: options.loop || false,
287
- yoyo: options.yoyo || false,
288
-
289
- // État interne
290
- startTime: null,
291
- delayStartTime: null,
292
- progress: 0,
293
- isDelaying: options.delay > 0,
294
- isReversed: false,
295
- originalValues: {}
296
- };
297
-
298
- // Sauvegarder les valeurs originales
299
- for (let prop in animation.to) {
300
- if (animation.from[prop] === undefined) {
301
- animation.from[prop] = component[prop];
302
- }
303
- animation.originalValues[prop] = component[prop];
304
- }
305
-
306
- this.animations.set(animationId, animation);
307
-
308
- if (!this.isRunning) {
309
- this.start();
310
- }
311
-
312
- return animationId;
313
- }
314
-
315
- /**
316
- * Anime plusieurs propriétés en séquence
317
- * @param {Component} component - Composant à animer
318
- * @param {Array} sequence - Tableau d'options d'animation
319
- * @returns {Promise} Promesse résolue à la fin de la séquence
320
- */
321
- async animateSequence(component, sequence) {
322
- for (let options of sequence) {
323
- await new Promise(resolve => {
324
- this.animate(component, {
325
- ...options,
326
- onComplete: () => {
327
- if (options.onComplete) options.onComplete();
328
- resolve();
329
- }
330
- });
331
- });
332
- }
333
- }
334
-
335
- /**
336
- * Anime plusieurs composants en parallèle
337
- * @param {Array} animations - Tableau de {component, options}
338
- * @returns {Promise} Promesse résolue quand toutes sont finies
339
- */
340
- async animateParallel(animations) {
341
- const promises = animations.map(({component, options}) => {
342
- return new Promise(resolve => {
343
- this.animate(component, {
344
- ...options,
345
- onComplete: () => {
346
- if (options.onComplete) options.onComplete();
347
- resolve();
348
- }
349
- });
350
- });
351
- });
352
-
353
- return Promise.all(promises);
354
- }
355
-
356
- /**
357
- * Crée une animation de rebond
358
- * @param {Component} component - Composant
359
- * @param {Object} options - Options
360
- */
361
- bounce(component, options = {}) {
362
- const originalY = component.y;
363
- const height = options.height || 50;
364
-
365
- return this.animate(component, {
366
- from: { y: originalY },
367
- to: { y: originalY - height },
368
- duration: options.duration || 400,
369
- easing: 'easeOutQuad',
370
- yoyo: true,
371
- onComplete: options.onComplete
372
- });
373
- }
374
-
375
- /**
376
- * Crée une animation de shake (tremblement)
377
- * @param {Component} component - Composant
378
- * @param {Object} options - Options
379
- */
380
- shake(component, options = {}) {
381
- const originalX = component.x;
382
- const intensity = options.intensity || 10;
383
- const shakes = options.shakes || 4;
384
- const duration = options.duration || 400;
385
-
386
- const sequence = [];
387
- for (let i = 0; i < shakes; i++) {
388
- sequence.push({
389
- to: { x: originalX + (i % 2 === 0 ? intensity : -intensity) },
390
- duration: duration / (shakes * 2),
391
- easing: 'linear'
392
- });
393
- }
394
- sequence.push({
395
- to: { x: originalX },
396
- duration: duration / (shakes * 2),
397
- easing: 'linear',
398
- onComplete: options.onComplete
399
- });
400
-
401
- return this.animateSequence(component, sequence);
402
- }
403
-
404
- /**
405
- * Crée une animation de pulsation (scale)
406
- * @param {Component} component - Composant
407
- * @param {Object} options - Options
408
- */
409
- pulse(component, options = {}) {
410
- const originalWidth = component.width;
411
- const originalHeight = component.height;
412
- const scale = options.scale || 1.1;
413
-
414
- return this.animate(component, {
415
- from: {
416
- width: originalWidth,
417
- height: originalHeight
418
- },
419
- to: {
420
- width: originalWidth * scale,
421
- height: originalHeight * scale
422
- },
423
- duration: options.duration || 300,
424
- easing: 'easeInOutQuad',
425
- yoyo: true,
426
- loop: options.loop || false,
427
- onComplete: options.onComplete
428
- });
429
- }
430
-
431
- /**
432
- * Crée une animation de fade (opacité)
433
- * @param {Component} component - Composant
434
- * @param {Object} options - Options
435
- */
436
- fade(component, options = {}) {
437
- // Ajouter une propriété opacity si elle n'existe pas
438
- if (component.opacity === undefined) {
439
- component.opacity = 1;
440
- }
441
-
442
- return this.animate(component, {
443
- from: { opacity: options.from !== undefined ? options.from : component.opacity },
444
- to: { opacity: options.to !== undefined ? options.to : 0 },
445
- duration: options.duration || 300,
446
- easing: options.easing || 'linear',
447
- onComplete: options.onComplete
448
- });
449
- }
450
-
451
- /**
452
- * Crée une animation de slide (glissement)
453
- * @param {Component} component - Composant
454
- * @param {Object} options - Options
455
- */
456
- slide(component, options = {}) {
457
- return this.animate(component, {
458
- from: options.from || { x: component.x, y: component.y },
459
- to: options.to || { x: component.x + 100, y: component.y },
460
- duration: options.duration || 400,
461
- easing: options.easing || 'easeOutQuad',
462
- onComplete: options.onComplete
463
- });
464
- }
465
-
466
- /**
467
- * Crée une animation de rotation
468
- * @param {Component} component - Composant
469
- * @param {Object} options - Options
470
- */
471
- rotate(component, options = {}) {
472
- if (component.rotation === undefined) {
473
- component.rotation = 0;
474
- }
475
-
476
- return this.animate(component, {
477
- from: { rotation: options.from !== undefined ? options.from : component.rotation },
478
- to: { rotation: options.to !== undefined ? options.to : 360 },
479
- duration: options.duration || 1000,
480
- easing: options.easing || 'linear',
481
- loop: options.loop || false,
482
- onComplete: options.onComplete
483
- });
484
- }
485
-
486
- /**
487
- * Arrête une animation
488
- * @param {string} animationId - ID de l'animation
489
- */
490
- stop(animationId) {
491
- this.animations.delete(animationId);
492
-
493
- if (this.animations.size === 0) {
494
- this.isRunning = false;
495
- if (this.animationFrameId) {
496
- cancelAnimationFrame(this.animationFrameId);
497
- this.animationFrameId = null;
498
- }
499
- }
500
- }
501
-
502
- /**
503
- * Arrête toutes les animations d'un composant
504
- * @param {Component} component - Composant
505
- */
506
- stopAll(component) {
507
- const toDelete = [];
508
-
509
- for (let [id, anim] of this.animations) {
510
- if (anim.component === component) {
511
- toDelete.push(id);
512
- }
513
- }
514
-
515
- toDelete.forEach(id => this.stop(id));
516
- }
517
-
518
- /**
519
- * Démarre le moteur d'animation
520
- * @private
521
- */
522
- start() {
523
- this.isRunning = true;
524
- this.lastTime = performance.now();
525
- this.update();
526
- }
527
-
528
- /**
529
- * Met à jour toutes les animations (avec Worker et batching)
530
- * @private
531
- */
532
- update() {
533
- const currentTime = performance.now();
534
-
535
- if (this.workerEnabled && this.worker) {
536
- // Utiliser le Worker pour les calculs
537
- this.updateWithWorker(currentTime);
538
- } else {
539
- // Fallback sur le thread principal
540
- this.updateOnMainThread(currentTime);
541
- }
542
-
543
- // Continuer l'animation
544
- if (this.animations.size > 0) {
545
- this.animationFrameId = requestAnimationFrame(() => this.update());
546
- } else {
547
- this.isRunning = false;
548
- }
549
- }
550
-
551
- /**
552
- * Met à jour avec le Worker (batching automatique)
553
- * @private
554
- */
555
- updateWithWorker(currentTime) {
556
- const animationsArray = [];
557
-
558
- for (let [id, anim] of this.animations) {
559
- // Préparer les données pour le Worker (sans les callbacks et le composant)
560
- animationsArray.push({
561
- id: anim.id,
562
- from: anim.from,
563
- to: anim.to,
564
- duration: anim.duration,
565
- easing: anim.easing,
566
- delay: anim.delay,
567
- loop: anim.loop,
568
- yoyo: anim.yoyo,
569
- startTime: anim.startTime,
570
- delayStartTime: anim.delayStartTime,
571
- isDelaying: anim.isDelaying,
572
- isReversed: anim.isReversed
573
- });
574
- }
575
-
576
- if (animationsArray.length > 0) {
577
- this.worker.postMessage({
578
- type: 'CALCULATE_BATCH',
579
- data: {
580
- animations: animationsArray,
581
- currentTime: currentTime
582
- }
583
- });
584
- }
585
- }
586
-
587
- /**
588
- * Met à jour sur le thread principal (fallback)
589
- * @private
590
- */
591
- updateOnMainThread(currentTime) {
592
- const toDelete = [];
593
-
594
- for (let [id, anim] of this.animations) {
595
- // Gérer le délai
596
- if (anim.isDelaying) {
597
- if (!anim.delayStartTime) {
598
- anim.delayStartTime = currentTime;
599
- }
600
-
601
- if (currentTime - anim.delayStartTime >= anim.delay) {
602
- anim.isDelaying = false;
603
- anim.startTime = currentTime;
604
- }
605
- continue;
606
- }
607
-
608
- // Initialiser le temps de départ
609
- if (!anim.startTime) {
610
- anim.startTime = currentTime;
611
- }
612
-
613
- // Calculer la progression
614
- const elapsed = currentTime - anim.startTime;
615
- let progress = Math.min(elapsed / anim.duration, 1);
616
-
617
- // Appliquer l'easing
618
- const easedProgress = this.applyEasing(progress, anim.easing);
619
-
620
- // Inverser si yoyo
621
- const actualProgress = anim.isReversed ? 1 - easedProgress : easedProgress;
622
-
623
- // Mettre à jour les propriétés du composant
624
- for (let prop in anim.to) {
625
- const from = anim.from[prop];
626
- const to = anim.to[prop];
627
- const value = from + (to - from) * actualProgress;
628
- anim.component[prop] = value;
629
- }
630
-
631
- // Callback onUpdate
632
- if (anim.onUpdate) {
633
- anim.onUpdate(actualProgress);
634
- }
635
-
636
- // Animation terminée
637
- if (progress >= 1) {
638
- if (anim.yoyo && !anim.isReversed) {
639
- // Inverser pour le yoyo
640
- anim.isReversed = true;
641
- anim.startTime = currentTime;
642
- } else if (anim.loop) {
643
- // Recommencer
644
- anim.startTime = currentTime;
645
- anim.isReversed = false;
646
- } else {
647
- // Terminer
648
- if (anim.onComplete) {
649
- anim.onComplete();
650
- }
651
- toDelete.push(id);
652
- }
653
- }
654
- }
655
-
656
- // Nettoyer les animations terminées
657
- toDelete.forEach(id => this.stop(id));
658
- }
659
-
660
- /**
661
- * Applique une fonction d'easing
662
- * @param {number} t - Progression (0-1)
663
- * @param {string} easingName - Nom de l'easing
664
- * @returns {number} Valeur easée
665
- * @private
666
- */
667
- applyEasing(t, easingName) {
668
- const easings = {
669
- linear: t => t,
670
- easeInQuad: t => t * t,
671
- easeOutQuad: t => t * (2 - t),
672
- easeInOutQuad: t => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
673
- easeInCubic: t => t * t * t,
674
- easeOutCubic: t => (--t) * t * t + 1,
675
- easeInOutCubic: t => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
676
- easeInQuart: t => t * t * t * t,
677
- easeOutQuart: t => 1 - (--t) * t * t * t,
678
- easeInOutQuart: t => t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t,
679
- easeInElastic: t => {
680
- const c4 = (2 * Math.PI) / 3;
681
- return t === 0 ? 0 : t === 1 ? 1 : -Math.pow(2, 10 * t - 10) * Math.sin((t * 10 - 10.75) * c4);
682
- },
683
- easeOutElastic: t => {
684
- const c4 = (2 * Math.PI) / 3;
685
- return t === 0 ? 0 : t === 1 ? 1 : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
686
- },
687
- easeOutBounce: t => {
688
- const n1 = 7.5625;
689
- const d1 = 2.75;
690
- if (t < 1 / d1) return n1 * t * t;
691
- else if (t < 2 / d1) return n1 * (t -= 1.5 / d1) * t + 0.75;
692
- else if (t < 2.5 / d1) return n1 * (t -= 2.25 / d1) * t + 0.9375;
693
- else return n1 * (t -= 2.625 / d1) * t + 0.984375;
694
- }
695
- };
696
-
697
- return (easings[easingName] || easings.linear)(t);
698
- }
699
-
700
- /**
701
- * Génère un ID unique
702
- * @returns {string} ID unique
703
- * @private
704
- */
705
- generateId() {
706
- return `anim_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
707
- }
708
-
709
- /**
710
- * Nettoie toutes les animations
711
- */
712
- clear() {
713
- this.animations.clear();
714
- this.isRunning = false;
715
- if (this.animationFrameId) {
716
- cancelAnimationFrame(this.animationFrameId);
717
- this.animationFrameId = null;
718
- }
719
- this.clearOffscreenCache();
720
- }
721
-
722
- /**
723
- * Nettoie le Worker
724
- */
725
- destroy() {
726
- this.clear();
727
- if (this.worker) {
728
- this.worker.terminate();
729
- this.worker = null;
730
- }
731
- }
732
- }
733
-
734
- export default AnimationEngine;