falling-animation 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,676 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.FallingAnimation = {}));
5
+ })(this, (function (exports) { 'use strict';
6
+
7
+ /**
8
+ * Utility functions for falling-animation
9
+ */
10
+ /**
11
+ * Generate a random number between min and max
12
+ */
13
+ function randomRange(min, max) {
14
+ return Math.random() * (max - min) + min;
15
+ }
16
+ /**
17
+ * Generate a random number from a RangeValue
18
+ */
19
+ function randomFromRange(range) {
20
+ return randomRange(range.min, range.max);
21
+ }
22
+ /**
23
+ * Pick a random item from an array
24
+ */
25
+ function randomPick(array) {
26
+ return array[Math.floor(Math.random() * array.length)];
27
+ }
28
+ /**
29
+ * Pick a random item based on weights
30
+ */
31
+ function weightedRandomPick(items) {
32
+ var _a;
33
+ const totalWeight = items.reduce((sum, item) => { var _a; return sum + ((_a = item.weight) !== null && _a !== void 0 ? _a : 1); }, 0);
34
+ let random = Math.random() * totalWeight;
35
+ for (const item of items) {
36
+ random -= (_a = item.weight) !== null && _a !== void 0 ? _a : 1;
37
+ if (random <= 0) {
38
+ return item;
39
+ }
40
+ }
41
+ return items[items.length - 1];
42
+ }
43
+ /**
44
+ * Generate a unique ID
45
+ */
46
+ let idCounter = 0;
47
+ function generateId() {
48
+ return ++idCounter;
49
+ }
50
+ /**
51
+ * Resolve container from element or selector
52
+ */
53
+ function resolveContainer(container) {
54
+ if (!container) {
55
+ return document.body;
56
+ }
57
+ if (typeof container === 'string') {
58
+ const element = document.querySelector(container);
59
+ if (!element) {
60
+ console.warn(`[falling-animation] Container "${container}" not found, using document.body`);
61
+ return document.body;
62
+ }
63
+ return element;
64
+ }
65
+ return container;
66
+ }
67
+ /**
68
+ * Throttle function calls
69
+ */
70
+ function throttle(func, limit) {
71
+ let inThrottle = false;
72
+ return function (...args) {
73
+ if (!inThrottle) {
74
+ func.apply(this, args);
75
+ inThrottle = true;
76
+ setTimeout(() => (inThrottle = false), limit);
77
+ }
78
+ };
79
+ }
80
+
81
+ /**
82
+ * Animation functions for falling particles
83
+ * Each animation modifies particle state based on deltaTime and elapsed time
84
+ */
85
+ /**
86
+ * Simple vertical fall - no special effects
87
+ */
88
+ const fall = (particle, deltaTime) => {
89
+ // Skip movement if speed is 0
90
+ if (particle.vy === 0 && particle.vx === 0)
91
+ return;
92
+ particle.y += particle.vy * deltaTime;
93
+ particle.x += particle.vx * deltaTime;
94
+ };
95
+ /**
96
+ * Swing - pendulum-like swinging motion while falling
97
+ */
98
+ const swing = (particle, deltaTime, elapsed) => {
99
+ const swingAmplitude = 30; // pixels
100
+ const swingFrequency = 0.002; // oscillations per ms
101
+ // Slight rotation based on swing - always animate
102
+ particle.rotation = Math.sin((elapsed + particle.phase) * swingFrequency) * 20;
103
+ // Skip movement if speed is 0
104
+ if (particle.vy === 0 && particle.vx === 0)
105
+ return;
106
+ particle.y += particle.vy * deltaTime;
107
+ // Calculate swing offset
108
+ const swingOffset = Math.sin((elapsed + particle.phase) * swingFrequency) * swingAmplitude;
109
+ particle.x += particle.vx * deltaTime + (swingOffset * 0.05);
110
+ };
111
+ /**
112
+ * Rotate - continuous 360° rotation while falling
113
+ */
114
+ const rotate = (particle, deltaTime) => {
115
+ // Continuous rotation - always animate
116
+ particle.rotation += particle.rotationSpeed * deltaTime;
117
+ // Skip movement if speed is 0
118
+ if (particle.vy === 0 && particle.vx === 0)
119
+ return;
120
+ particle.y += particle.vy * deltaTime;
121
+ particle.x += particle.vx * deltaTime;
122
+ };
123
+ /**
124
+ * Flutter - butterfly-like fluttering motion
125
+ */
126
+ const flutter = (particle, deltaTime, elapsed) => {
127
+ const flutterFrequency = 0.005;
128
+ // Tilt based on direction - always animate
129
+ particle.rotation = Math.sin((elapsed + particle.phase) * flutterFrequency) * 30;
130
+ // Skip movement if speed is 0
131
+ if (particle.vy === 0 && particle.vx === 0)
132
+ return;
133
+ const flutterAmplitude = 40;
134
+ const verticalWobble = 0.3;
135
+ // Horizontal flutter
136
+ const flutter = Math.sin((elapsed + particle.phase) * flutterFrequency) * flutterAmplitude;
137
+ particle.x += particle.vx * deltaTime + flutter * 0.03;
138
+ // Vertical movement with slight wobble
139
+ const wobble = Math.sin((elapsed + particle.phase) * flutterFrequency * 2) * verticalWobble;
140
+ particle.y += (particle.vy + wobble) * deltaTime;
141
+ };
142
+ /**
143
+ * Spiral - spiraling down pattern
144
+ */
145
+ const spiral = (particle, deltaTime, elapsed) => {
146
+ const spiralSpeed = 0.003;
147
+ const angle = (elapsed + particle.phase) * spiralSpeed;
148
+ // Rotate with spiral - always animate
149
+ particle.rotation = angle * (180 / Math.PI);
150
+ // Skip movement if speed is 0
151
+ if (particle.vy === 0 && particle.vx === 0)
152
+ return;
153
+ const spiralRadius = 25;
154
+ particle.y += particle.vy * deltaTime;
155
+ // Spiral motion
156
+ particle.x += particle.vx * deltaTime + Math.cos(angle) * spiralRadius * 0.02;
157
+ };
158
+ /**
159
+ * Tumble - chaotic tumbling motion
160
+ */
161
+ const tumble = (particle, deltaTime, elapsed) => {
162
+ var _a, _b, _c;
163
+ const tumbleSpeed = (_a = particle.data.tumbleSpeed) !== null && _a !== void 0 ? _a : 5;
164
+ // Fast tumbling rotation - always animate
165
+ particle.rotation += tumbleSpeed * deltaTime;
166
+ // Skip movement if speed is 0
167
+ if (particle.vy === 0 && particle.vx === 0)
168
+ return;
169
+ const wobbleX = (_b = particle.data.wobbleX) !== null && _b !== void 0 ? _b : 0.02;
170
+ const wobbleY = (_c = particle.data.wobbleY) !== null && _c !== void 0 ? _c : 0.01;
171
+ particle.y += particle.vy * deltaTime;
172
+ // Chaotic horizontal movement
173
+ particle.x += particle.vx * deltaTime +
174
+ Math.sin((elapsed + particle.phase) * wobbleX) * 20 * 0.02;
175
+ // Add some vertical variation
176
+ particle.y += Math.sin((elapsed + particle.phase * 1.5) * wobbleY) * 0.5;
177
+ };
178
+ /**
179
+ * Zigzag - zigzag falling pattern
180
+ */
181
+ const zigzag = (particle, deltaTime, elapsed) => {
182
+ const zigzagFrequency = 0.002;
183
+ const period = 1 / zigzagFrequency;
184
+ const t = ((elapsed + particle.phase) % period) / period;
185
+ const triangleWave = Math.abs(t * 2 - 1) * 2 - 1;
186
+ // Tilt in direction of movement - always animate
187
+ particle.rotation = triangleWave * 25;
188
+ // Skip movement if speed is 0
189
+ if (particle.vy === 0 && particle.vx === 0)
190
+ return;
191
+ const zigzagWidth = 50;
192
+ particle.y += particle.vy * deltaTime;
193
+ // Create zigzag using triangle wave
194
+ particle.x += particle.vx * deltaTime + triangleWave * zigzagWidth * 0.02;
195
+ };
196
+ /**
197
+ * Float - slow floating descent with gentle movement
198
+ */
199
+ const float = (particle, deltaTime, elapsed) => {
200
+ const floatFrequency = 0.001;
201
+ // Gentle rotation - always animate
202
+ particle.rotation = Math.sin((elapsed + particle.phase) * floatFrequency) * 10;
203
+ // Skip movement if speed is 0
204
+ if (particle.vy === 0 && particle.vx === 0)
205
+ return;
206
+ const floatAmplitudeX = 20;
207
+ const floatAmplitudeY = 5;
208
+ // Very slow descent with vertical wobble
209
+ const yWobble = Math.sin((elapsed + particle.phase) * floatFrequency * 2) * floatAmplitudeY;
210
+ particle.y += (particle.vy * 0.5 + yWobble * 0.01) * deltaTime;
211
+ // Gentle horizontal drift
212
+ const xDrift = Math.sin((elapsed + particle.phase) * floatFrequency) * floatAmplitudeX;
213
+ particle.x += particle.vx * deltaTime + xDrift * 0.01;
214
+ };
215
+ /**
216
+ * Animation registry - all available animations
217
+ */
218
+ const animations = {
219
+ fall,
220
+ swing,
221
+ rotate,
222
+ flutter,
223
+ spiral,
224
+ tumble,
225
+ zigzag,
226
+ float
227
+ };
228
+ /**
229
+ * Get animation function by name
230
+ */
231
+ function getAnimation(name) {
232
+ var _a;
233
+ return (_a = animations[name]) !== null && _a !== void 0 ? _a : fall;
234
+ }
235
+
236
+ /**
237
+ * Particle class - manages individual falling objects
238
+ */
239
+ /**
240
+ * Speed multiplier to convert user-friendly speed units to px/ms
241
+ * speed = 1 means ~40 pixels per second (~1cm/s at 96 DPI)
242
+ * speed = 0.1 means ~4 pixels per second (~1mm/s)
243
+ * speed = 0 means standing still
244
+ */
245
+ const SPEED_MULTIPLIER = 0.04; // 40 px/s per unit, divided by 1000 for ms
246
+ class Particle {
247
+ constructor(options) {
248
+ this.options = options;
249
+ this.id = generateId();
250
+ this.age = 0;
251
+ this.phase = Math.random() * Math.PI * 2;
252
+ this.data = {};
253
+ // Get container dimensions
254
+ this.containerWidth = options.container.clientWidth;
255
+ this.containerHeight = options.container.clientHeight;
256
+ // Pick random object
257
+ const object = weightedRandomPick(options.objects);
258
+ // Initialize position at top with random x
259
+ this.x = randomRange(-50, this.containerWidth + 50);
260
+ this.y = -50;
261
+ // Initialize velocity (apply speed multiplier for intuitive units)
262
+ // speed=1 → ~40px/s (1cm/s), speed=0.1 → ~4px/s (1mm/s)
263
+ this.vy = randomFromRange(options.speed) * SPEED_MULTIPLIER;
264
+ this.vx = options.wind * SPEED_MULTIPLIER * randomRange(0.5, 1.5);
265
+ // Initialize size and opacity
266
+ this.size = randomFromRange(options.size);
267
+ this.opacity = randomFromRange(options.opacity);
268
+ // Initialize rotation
269
+ this.rotation = randomRange(0, 360);
270
+ this.rotationSpeed = randomRange(-3, 3);
271
+ // Pick animation
272
+ this.animation = randomPick(options.animation);
273
+ // Initialize animation-specific data
274
+ this.initAnimationData();
275
+ // Create DOM element
276
+ this.element = this.createElement(object);
277
+ }
278
+ /**
279
+ * Initialize animation-specific data
280
+ */
281
+ initAnimationData() {
282
+ if (this.animation === 'tumble') {
283
+ this.data.tumbleSpeed = randomRange(3, 8);
284
+ this.data.wobbleX = randomRange(0.01, 0.03);
285
+ this.data.wobbleY = randomRange(0.005, 0.015);
286
+ }
287
+ }
288
+ /**
289
+ * Create DOM element for the particle
290
+ */
291
+ createElement(object) {
292
+ var _a, _b, _c, _d;
293
+ const element = document.createElement('div');
294
+ element.className = 'falling-particle';
295
+ element.setAttribute('data-particle-id', String(this.id));
296
+ // Set content based on type
297
+ switch (object.type) {
298
+ case 'emoji':
299
+ element.textContent = (_a = object.content) !== null && _a !== void 0 ? _a : '❄️';
300
+ element.style.fontSize = `${this.size}px`;
301
+ element.style.lineHeight = '1';
302
+ break;
303
+ case 'image':
304
+ const img = document.createElement('img');
305
+ img.src = (_c = (_b = object.src) !== null && _b !== void 0 ? _b : object.content) !== null && _c !== void 0 ? _c : '';
306
+ img.alt = '';
307
+ img.style.width = `${this.size}px`;
308
+ img.style.height = `${this.size}px`;
309
+ img.style.objectFit = 'contain';
310
+ img.draggable = false;
311
+ element.appendChild(img);
312
+ break;
313
+ case 'html':
314
+ element.innerHTML = (_d = object.content) !== null && _d !== void 0 ? _d : '';
315
+ break;
316
+ }
317
+ // Apply base styles
318
+ Object.assign(element.style, {
319
+ position: 'absolute',
320
+ pointerEvents: 'none',
321
+ userSelect: 'none',
322
+ willChange: 'transform, opacity',
323
+ opacity: String(this.opacity),
324
+ left: '0',
325
+ top: '0',
326
+ transform: this.getTransform()
327
+ });
328
+ return element;
329
+ }
330
+ /**
331
+ * Get CSS transform string
332
+ */
333
+ getTransform() {
334
+ return `translate3d(${this.x}px, ${this.y}px, 0) rotate(${this.rotation}deg)`;
335
+ }
336
+ /**
337
+ * Update particle state
338
+ */
339
+ update(deltaTime, elapsed) {
340
+ this.age += deltaTime;
341
+ // Apply animation
342
+ const animationFn = getAnimation(this.animation);
343
+ animationFn(this, deltaTime, elapsed);
344
+ // Update DOM
345
+ this.element.style.transform = this.getTransform();
346
+ }
347
+ /**
348
+ * Check if particle is out of bounds
349
+ */
350
+ isOutOfBounds() {
351
+ return (this.y > this.containerHeight + 100 ||
352
+ this.x < -100 ||
353
+ this.x > this.containerWidth + 100);
354
+ }
355
+ /**
356
+ * Update container dimensions (for resize handling)
357
+ */
358
+ updateContainerSize(width, height) {
359
+ this.containerWidth = width;
360
+ this.containerHeight = height;
361
+ }
362
+ /**
363
+ * Remove particle from DOM
364
+ */
365
+ destroy() {
366
+ this.element.remove();
367
+ }
368
+ }
369
+
370
+ /**
371
+ * FallingAnimation - Main class for creating falling object animations
372
+ */
373
+ /** Default configuration values */
374
+ const DEFAULTS = {
375
+ speed: { min: 2, max: 5 },
376
+ spawnRate: 3,
377
+ maxParticles: 50,
378
+ animation: ['fall'],
379
+ size: { min: 20, max: 40 },
380
+ opacity: { min: 0.6, max: 1 },
381
+ wind: 0,
382
+ autoStart: true,
383
+ zIndex: 9999,
384
+ responsive: true
385
+ };
386
+ class FallingAnimation {
387
+ constructor(options) {
388
+ this.particles = [];
389
+ this.wrapper = null;
390
+ this.isRunning = false;
391
+ this.isPaused = false;
392
+ this.animationId = null;
393
+ this.lastSpawnTime = 0;
394
+ this.startTime = 0;
395
+ this.lastFrameTime = 0;
396
+ this.resizeHandler = null;
397
+ /**
398
+ * Main animation loop
399
+ */
400
+ this.animate = (currentTime) => {
401
+ if (!this.isRunning)
402
+ return;
403
+ // Calculate delta time
404
+ if (this.lastFrameTime === 0) {
405
+ this.lastFrameTime = currentTime;
406
+ this.startTime = currentTime;
407
+ }
408
+ const deltaTime = Math.min(currentTime - this.lastFrameTime, 50); // Cap at 50ms
409
+ const elapsed = currentTime - this.startTime;
410
+ this.lastFrameTime = currentTime;
411
+ // Spawn new particles based on rate
412
+ const spawnInterval = 1000 / this.options.spawnRate;
413
+ if (currentTime - this.lastSpawnTime >= spawnInterval) {
414
+ this.spawnParticle();
415
+ this.lastSpawnTime = currentTime;
416
+ }
417
+ // Update particles
418
+ const particlesToRemove = [];
419
+ for (const particle of this.particles) {
420
+ particle.update(deltaTime, elapsed);
421
+ if (particle.isOutOfBounds()) {
422
+ particlesToRemove.push(particle);
423
+ }
424
+ }
425
+ // Remove out-of-bounds particles
426
+ particlesToRemove.forEach(p => this.removeParticle(p));
427
+ // Continue animation loop
428
+ this.animationId = requestAnimationFrame(this.animate);
429
+ };
430
+ // Validate required options
431
+ if (!options.objects || options.objects.length === 0) {
432
+ throw new Error('[falling-animation] "objects" option is required and must not be empty');
433
+ }
434
+ // Resolve options with defaults
435
+ this.options = this.resolveOptions(options);
436
+ // Create wrapper element
437
+ this.createWrapper();
438
+ // Setup resize handler if responsive
439
+ if (this.options.responsive) {
440
+ this.setupResizeHandler();
441
+ }
442
+ // Auto start if enabled
443
+ if (this.options.autoStart) {
444
+ this.start();
445
+ }
446
+ }
447
+ /**
448
+ * Merge user options with defaults
449
+ */
450
+ resolveOptions(options) {
451
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
452
+ const container = resolveContainer(options.container);
453
+ // Normalize animation to array
454
+ let animation;
455
+ if (!options.animation) {
456
+ animation = DEFAULTS.animation;
457
+ }
458
+ else if (typeof options.animation === 'string') {
459
+ animation = [options.animation];
460
+ }
461
+ else {
462
+ animation = options.animation;
463
+ }
464
+ return {
465
+ container,
466
+ objects: options.objects,
467
+ speed: (_a = options.speed) !== null && _a !== void 0 ? _a : DEFAULTS.speed,
468
+ spawnRate: (_b = options.spawnRate) !== null && _b !== void 0 ? _b : DEFAULTS.spawnRate,
469
+ maxParticles: (_c = options.maxParticles) !== null && _c !== void 0 ? _c : DEFAULTS.maxParticles,
470
+ animation,
471
+ size: (_d = options.size) !== null && _d !== void 0 ? _d : DEFAULTS.size,
472
+ opacity: (_e = options.opacity) !== null && _e !== void 0 ? _e : DEFAULTS.opacity,
473
+ wind: (_f = options.wind) !== null && _f !== void 0 ? _f : DEFAULTS.wind,
474
+ autoStart: (_g = options.autoStart) !== null && _g !== void 0 ? _g : DEFAULTS.autoStart,
475
+ zIndex: (_h = options.zIndex) !== null && _h !== void 0 ? _h : DEFAULTS.zIndex,
476
+ responsive: (_j = options.responsive) !== null && _j !== void 0 ? _j : DEFAULTS.responsive
477
+ };
478
+ }
479
+ /**
480
+ * Create wrapper element for particles
481
+ */
482
+ createWrapper() {
483
+ this.wrapper = document.createElement('div');
484
+ this.wrapper.className = 'falling-animation-wrapper';
485
+ // Apply styles
486
+ Object.assign(this.wrapper.style, {
487
+ position: this.options.container === document.body ? 'fixed' : 'absolute',
488
+ top: '0',
489
+ left: '0',
490
+ width: '100%',
491
+ height: '100%',
492
+ overflow: 'hidden',
493
+ pointerEvents: 'none',
494
+ zIndex: String(this.options.zIndex)
495
+ });
496
+ // Ensure container has position for absolute wrapper
497
+ if (this.options.container !== document.body) {
498
+ const containerPosition = getComputedStyle(this.options.container).position;
499
+ if (containerPosition === 'static') {
500
+ this.options.container.style.position = 'relative';
501
+ }
502
+ }
503
+ this.options.container.appendChild(this.wrapper);
504
+ }
505
+ /**
506
+ * Setup resize handler for responsive behavior
507
+ */
508
+ setupResizeHandler() {
509
+ this.resizeHandler = throttle(() => {
510
+ const width = this.options.container.clientWidth;
511
+ const height = this.options.container.clientHeight;
512
+ this.particles.forEach(particle => {
513
+ particle.updateContainerSize(width, height);
514
+ });
515
+ }, 200);
516
+ window.addEventListener('resize', this.resizeHandler);
517
+ }
518
+ /**
519
+ * Spawn a new particle
520
+ */
521
+ spawnParticle() {
522
+ if (this.particles.length >= this.options.maxParticles) {
523
+ return;
524
+ }
525
+ const particle = new Particle(this.options);
526
+ this.particles.push(particle);
527
+ if (this.wrapper) {
528
+ this.wrapper.appendChild(particle.element);
529
+ }
530
+ }
531
+ /**
532
+ * Remove a particle
533
+ */
534
+ removeParticle(particle) {
535
+ const index = this.particles.indexOf(particle);
536
+ if (index > -1) {
537
+ this.particles.splice(index, 1);
538
+ particle.destroy();
539
+ }
540
+ }
541
+ /**
542
+ * Start the animation
543
+ */
544
+ start() {
545
+ if (this.isRunning)
546
+ return;
547
+ this.isRunning = true;
548
+ this.isPaused = false;
549
+ this.lastFrameTime = 0;
550
+ this.lastSpawnTime = 0;
551
+ this.animationId = requestAnimationFrame(this.animate);
552
+ }
553
+ /**
554
+ * Stop the animation and clear all particles
555
+ */
556
+ stop() {
557
+ this.isRunning = false;
558
+ this.isPaused = false;
559
+ if (this.animationId !== null) {
560
+ cancelAnimationFrame(this.animationId);
561
+ this.animationId = null;
562
+ }
563
+ // Clear all particles
564
+ this.particles.forEach(p => p.destroy());
565
+ this.particles = [];
566
+ }
567
+ /**
568
+ * Pause the animation (keeps particles in place)
569
+ */
570
+ pause() {
571
+ if (!this.isRunning || this.isPaused)
572
+ return;
573
+ this.isPaused = true;
574
+ this.isRunning = false;
575
+ if (this.animationId !== null) {
576
+ cancelAnimationFrame(this.animationId);
577
+ this.animationId = null;
578
+ }
579
+ }
580
+ /**
581
+ * Resume a paused animation
582
+ */
583
+ resume() {
584
+ if (this.isRunning || !this.isPaused)
585
+ return;
586
+ this.isRunning = true;
587
+ this.isPaused = false;
588
+ this.lastFrameTime = 0;
589
+ this.animationId = requestAnimationFrame(this.animate);
590
+ }
591
+ /**
592
+ * Update options dynamically
593
+ */
594
+ setOptions(newOptions) {
595
+ // Merge new options
596
+ if (newOptions.speed) {
597
+ this.options.speed = newOptions.speed;
598
+ }
599
+ if (newOptions.spawnRate !== undefined) {
600
+ this.options.spawnRate = newOptions.spawnRate;
601
+ }
602
+ if (newOptions.maxParticles !== undefined) {
603
+ this.options.maxParticles = newOptions.maxParticles;
604
+ }
605
+ if (newOptions.animation) {
606
+ this.options.animation = typeof newOptions.animation === 'string'
607
+ ? [newOptions.animation]
608
+ : newOptions.animation;
609
+ }
610
+ if (newOptions.size) {
611
+ this.options.size = newOptions.size;
612
+ }
613
+ if (newOptions.opacity) {
614
+ this.options.opacity = newOptions.opacity;
615
+ }
616
+ if (newOptions.wind !== undefined) {
617
+ this.options.wind = newOptions.wind;
618
+ }
619
+ if (newOptions.objects) {
620
+ this.options.objects = newOptions.objects;
621
+ }
622
+ }
623
+ /**
624
+ * Get current particle count
625
+ */
626
+ getParticleCount() {
627
+ return this.particles.length;
628
+ }
629
+ /**
630
+ * Check if animation is running
631
+ */
632
+ getIsRunning() {
633
+ return this.isRunning;
634
+ }
635
+ /**
636
+ * Check if animation is paused
637
+ */
638
+ getIsPaused() {
639
+ return this.isPaused;
640
+ }
641
+ /**
642
+ * Destroy the animation and clean up
643
+ */
644
+ destroy() {
645
+ this.stop();
646
+ // Remove wrapper
647
+ if (this.wrapper) {
648
+ this.wrapper.remove();
649
+ this.wrapper = null;
650
+ }
651
+ // Remove resize handler
652
+ if (this.resizeHandler) {
653
+ window.removeEventListener('resize', this.resizeHandler);
654
+ this.resizeHandler = null;
655
+ }
656
+ }
657
+ }
658
+
659
+ /**
660
+ * falling-animation
661
+ * A lightweight, customizable falling objects animation library
662
+ *
663
+ * @author phongdh
664
+ * @license MIT
665
+ */
666
+ // Main class
667
+
668
+ exports.FallingAnimation = FallingAnimation;
669
+ exports.animations = animations;
670
+ exports.default = FallingAnimation;
671
+ exports.getAnimation = getAnimation;
672
+
673
+ Object.defineProperty(exports, '__esModule', { value: true });
674
+
675
+ }));
676
+ //# sourceMappingURL=falling-animation.umd.js.map