masoneffect 2.0.4 → 2.0.5
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 +2 -2
- package/dist/core/count/index.d.ts +3 -2
- package/dist/core/count/index.d.ts.map +1 -1
- package/dist/core/textToParticle/index.d.ts +3 -3
- package/dist/core/textToParticle/index.d.ts.map +1 -1
- package/dist/core/typing/index.d.ts +3 -2
- package/dist/core/typing/index.d.ts.map +1 -1
- package/dist/core/utils/visibilityManager.d.ts +35 -0
- package/dist/core/utils/visibilityManager.d.ts.map +1 -0
- package/dist/count/core/count/index.d.ts +3 -2
- package/dist/count/core/count/index.d.ts.map +1 -1
- package/dist/count/core/textToParticle/index.d.ts +3 -3
- package/dist/count/core/textToParticle/index.d.ts.map +1 -1
- package/dist/count/core/typing/index.d.ts +3 -2
- package/dist/count/core/typing/index.d.ts.map +1 -1
- package/dist/count/core/utils/visibilityManager.d.ts +35 -0
- package/dist/count/core/utils/visibilityManager.d.ts.map +1 -0
- package/dist/count/index.cjs +1 -1
- package/dist/count/index.mjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/react/core/count/index.d.ts +3 -2
- package/dist/react/core/textToParticle/index.d.ts +3 -3
- package/dist/react/core/typing/index.d.ts +3 -2
- package/dist/react/core/utils/visibilityManager.d.ts +34 -0
- package/dist/react/count/core/count/index.d.ts +3 -2
- package/dist/react/count/core/count/index.d.ts.map +1 -1
- package/dist/react/count/core/textToParticle/index.d.ts +3 -3
- package/dist/react/count/core/textToParticle/index.d.ts.map +1 -1
- package/dist/react/count/core/typing/index.d.ts +3 -2
- package/dist/react/count/core/typing/index.d.ts.map +1 -1
- package/dist/react/count/core/utils/visibilityManager.d.ts +35 -0
- package/dist/react/count/core/utils/visibilityManager.d.ts.map +1 -0
- package/dist/react/count/index.cjs +1 -1
- package/dist/react/count/index.mjs +1 -1
- package/dist/react/textToParticle/core/count/index.d.ts +3 -2
- package/dist/react/textToParticle/core/count/index.d.ts.map +1 -1
- package/dist/react/textToParticle/core/textToParticle/index.d.ts +3 -3
- package/dist/react/textToParticle/core/textToParticle/index.d.ts.map +1 -1
- package/dist/react/textToParticle/core/typing/index.d.ts +3 -2
- package/dist/react/textToParticle/core/typing/index.d.ts.map +1 -1
- package/dist/react/textToParticle/core/utils/visibilityManager.d.ts +35 -0
- package/dist/react/textToParticle/core/utils/visibilityManager.d.ts.map +1 -0
- package/dist/react/textToParticle/index.cjs +1 -1
- package/dist/react/textToParticle/index.mjs +1 -1
- package/dist/react/typing/core/count/index.d.ts +3 -2
- package/dist/react/typing/core/count/index.d.ts.map +1 -1
- package/dist/react/typing/core/textToParticle/index.d.ts +3 -3
- package/dist/react/typing/core/textToParticle/index.d.ts.map +1 -1
- package/dist/react/typing/core/typing/index.d.ts +3 -2
- package/dist/react/typing/core/typing/index.d.ts.map +1 -1
- package/dist/react/typing/core/utils/visibilityManager.d.ts +35 -0
- package/dist/react/typing/core/utils/visibilityManager.d.ts.map +1 -0
- package/dist/react/typing/index.cjs +1 -1
- package/dist/react/typing/index.mjs +1 -1
- package/dist/svelte/count/index.cjs +1 -1
- package/dist/svelte/count/index.d.ts +41 -28
- package/dist/svelte/count/index.mjs +120 -42
- package/dist/svelte/index.cjs +1 -1
- package/dist/svelte/index.d.ts +41 -28
- package/dist/svelte/index.mjs +154 -107
- package/dist/svelte/textToParticle/index.cjs +1 -1
- package/dist/svelte/textToParticle/index.d.ts +41 -28
- package/dist/svelte/textToParticle/index.mjs +119 -33
- package/dist/svelte/typing/index.cjs +1 -1
- package/dist/svelte/typing/index.d.ts +41 -28
- package/dist/svelte/typing/index.mjs +117 -32
- package/dist/textToParticle/core/count/index.d.ts +3 -2
- package/dist/textToParticle/core/count/index.d.ts.map +1 -1
- package/dist/textToParticle/core/textToParticle/index.d.ts +3 -3
- package/dist/textToParticle/core/textToParticle/index.d.ts.map +1 -1
- package/dist/textToParticle/core/typing/index.d.ts +3 -2
- package/dist/textToParticle/core/typing/index.d.ts.map +1 -1
- package/dist/textToParticle/core/utils/visibilityManager.d.ts +35 -0
- package/dist/textToParticle/core/utils/visibilityManager.d.ts.map +1 -0
- package/dist/textToParticle/index.cjs +1 -1
- package/dist/textToParticle/index.mjs +1 -1
- package/dist/typing/core/count/index.d.ts +3 -2
- package/dist/typing/core/count/index.d.ts.map +1 -1
- package/dist/typing/core/textToParticle/index.d.ts +3 -3
- package/dist/typing/core/textToParticle/index.d.ts.map +1 -1
- package/dist/typing/core/typing/index.d.ts +3 -2
- package/dist/typing/core/typing/index.d.ts.map +1 -1
- package/dist/typing/core/utils/visibilityManager.d.ts +35 -0
- package/dist/typing/core/utils/visibilityManager.d.ts.map +1 -0
- package/dist/typing/index.cjs +1 -1
- package/dist/typing/index.mjs +1 -1
- package/dist/vue/count/index.cjs +1 -1
- package/dist/vue/count/index.d.ts +41 -28
- package/dist/vue/count/index.mjs +119 -41
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.d.ts +41 -28
- package/dist/vue/index.mjs +152 -105
- package/dist/vue/textToParticle/index.cjs +1 -1
- package/dist/vue/textToParticle/index.d.ts +41 -28
- package/dist/vue/textToParticle/index.mjs +119 -33
- package/dist/vue/typing/index.cjs +1 -1
- package/dist/vue/typing/index.d.ts +41 -28
- package/dist/vue/typing/index.mjs +116 -31
- package/package.json +1 -1
package/dist/vue/index.mjs
CHANGED
|
@@ -1,4 +1,105 @@
|
|
|
1
1
|
import { defineComponent, ref, watch, onMounted, onBeforeUnmount, createElementBlock, openBlock, normalizeStyle, normalizeClass, onUnmounted } from "vue";
|
|
2
|
+
class VisibilityManager {
|
|
3
|
+
constructor(container, options = {}) {
|
|
4
|
+
this.container = container;
|
|
5
|
+
this.options = {
|
|
6
|
+
threshold: options.threshold ?? 0.1,
|
|
7
|
+
rootMargin: options.rootMargin ?? "0px",
|
|
8
|
+
onVisible: options.onVisible,
|
|
9
|
+
onHidden: options.onHidden
|
|
10
|
+
};
|
|
11
|
+
this.intersectionObserver = null;
|
|
12
|
+
this.visibilityChangeHandler = null;
|
|
13
|
+
this.isVisible = false;
|
|
14
|
+
this.isPageVisible = typeof document !== "undefined" ? !document.hidden : true;
|
|
15
|
+
this.setupIntersectionObserver();
|
|
16
|
+
this.setupPageVisibility();
|
|
17
|
+
}
|
|
18
|
+
setupIntersectionObserver() {
|
|
19
|
+
if (typeof window === "undefined" || typeof window.IntersectionObserver === "undefined") {
|
|
20
|
+
this.isVisible = true;
|
|
21
|
+
if (this.isPageVisible && this.options.onVisible) {
|
|
22
|
+
this.options.onVisible();
|
|
23
|
+
}
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this.intersectionObserver = new IntersectionObserver(
|
|
27
|
+
(entries) => {
|
|
28
|
+
for (const entry of entries) {
|
|
29
|
+
if (entry.target !== this.container) continue;
|
|
30
|
+
if (entry.isIntersecting) {
|
|
31
|
+
this.isVisible = true;
|
|
32
|
+
if (this.isPageVisible && this.options.onVisible) {
|
|
33
|
+
this.options.onVisible();
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
this.isVisible = false;
|
|
37
|
+
if (this.options.onHidden) {
|
|
38
|
+
this.options.onHidden();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
threshold: this.options.threshold,
|
|
45
|
+
rootMargin: this.options.rootMargin
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
this.intersectionObserver.observe(this.container);
|
|
49
|
+
}
|
|
50
|
+
setupPageVisibility() {
|
|
51
|
+
if (typeof document === "undefined") return;
|
|
52
|
+
this.visibilityChangeHandler = () => {
|
|
53
|
+
const wasVisible = this.isPageVisible;
|
|
54
|
+
this.isPageVisible = !document.hidden;
|
|
55
|
+
if (document.hidden) {
|
|
56
|
+
if (this.options.onHidden) {
|
|
57
|
+
this.options.onHidden();
|
|
58
|
+
}
|
|
59
|
+
} else if (wasVisible !== this.isPageVisible) {
|
|
60
|
+
if (this.isVisible && this.options.onVisible) {
|
|
61
|
+
this.options.onVisible();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
document.addEventListener("visibilitychange", this.visibilityChangeHandler);
|
|
66
|
+
if (document.hidden && this.isVisible) {
|
|
67
|
+
if (this.options.onHidden) {
|
|
68
|
+
this.options.onHidden();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 현재 요소가 화면에 보이는지 확인
|
|
74
|
+
*/
|
|
75
|
+
getIsVisible() {
|
|
76
|
+
return this.isVisible && this.isPageVisible;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 옵션 업데이트
|
|
80
|
+
*/
|
|
81
|
+
updateOptions(newOptions) {
|
|
82
|
+
this.options = { ...this.options, ...newOptions };
|
|
83
|
+
if (this.intersectionObserver) {
|
|
84
|
+
this.intersectionObserver.disconnect();
|
|
85
|
+
this.intersectionObserver = null;
|
|
86
|
+
}
|
|
87
|
+
this.setupIntersectionObserver();
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 리소스 정리
|
|
91
|
+
*/
|
|
92
|
+
destroy() {
|
|
93
|
+
if (this.intersectionObserver) {
|
|
94
|
+
this.intersectionObserver.disconnect();
|
|
95
|
+
this.intersectionObserver = null;
|
|
96
|
+
}
|
|
97
|
+
if (this.visibilityChangeHandler && typeof document !== "undefined") {
|
|
98
|
+
document.removeEventListener("visibilitychange", this.visibilityChangeHandler);
|
|
99
|
+
this.visibilityChangeHandler = null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
2
103
|
function debounce(func, wait) {
|
|
3
104
|
let timeout = null;
|
|
4
105
|
return function executedFunction(...args) {
|
|
@@ -56,8 +157,7 @@ class TextToParticle {
|
|
|
56
157
|
this.mouse = { x: 0, y: 0, down: false };
|
|
57
158
|
this.animationId = null;
|
|
58
159
|
this.isRunning = false;
|
|
59
|
-
this.
|
|
60
|
-
this.intersectionObserver = null;
|
|
160
|
+
this.visibilityManager = null;
|
|
61
161
|
this.debounceDelay = options.debounceDelay ?? 150;
|
|
62
162
|
const boundHandleResize = this.handleResize.bind(this);
|
|
63
163
|
this.handleResize = debounce(boundHandleResize, this.debounceDelay);
|
|
@@ -72,39 +172,22 @@ class TextToParticle {
|
|
|
72
172
|
init() {
|
|
73
173
|
this.resize();
|
|
74
174
|
this.setupEventListeners();
|
|
75
|
-
this.
|
|
175
|
+
this.setupVisibilityManager();
|
|
76
176
|
if (this.config.onReady) {
|
|
77
177
|
this.config.onReady(this);
|
|
78
178
|
}
|
|
79
179
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (this.intersectionObserver) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
this.intersectionObserver = new IntersectionObserver(
|
|
90
|
-
(entries) => {
|
|
91
|
-
for (const entry of entries) {
|
|
92
|
-
if (entry.target !== this.container) continue;
|
|
93
|
-
if (entry.isIntersecting) {
|
|
94
|
-
this.isVisible = true;
|
|
95
|
-
this.start();
|
|
96
|
-
} else {
|
|
97
|
-
this.isVisible = false;
|
|
98
|
-
this.stop();
|
|
99
|
-
}
|
|
100
|
-
}
|
|
180
|
+
setupVisibilityManager() {
|
|
181
|
+
this.visibilityManager = new VisibilityManager(this.container, {
|
|
182
|
+
threshold: 0.1,
|
|
183
|
+
// 10% 이상 보일 때 동작
|
|
184
|
+
onVisible: () => {
|
|
185
|
+
this.start();
|
|
101
186
|
},
|
|
102
|
-
{
|
|
103
|
-
|
|
104
|
-
// 10% 이상 보일 때 동작
|
|
187
|
+
onHidden: () => {
|
|
188
|
+
this.stop();
|
|
105
189
|
}
|
|
106
|
-
);
|
|
107
|
-
this.intersectionObserver.observe(this.container);
|
|
190
|
+
});
|
|
108
191
|
}
|
|
109
192
|
resize() {
|
|
110
193
|
const width = this.config.width || this.container.clientWidth || window.innerWidth;
|
|
@@ -341,7 +424,10 @@ class TextToParticle {
|
|
|
341
424
|
p.y += p.vy;
|
|
342
425
|
}
|
|
343
426
|
this.ctx.fillStyle = this.config.particleColor;
|
|
344
|
-
const
|
|
427
|
+
const baseSize = 1920;
|
|
428
|
+
const currentSize = Math.min(this.W, this.H) / this.DPR;
|
|
429
|
+
const sizeRatio = Math.max(0.5, Math.min(2, currentSize / baseSize));
|
|
430
|
+
const r = this.config.pointSize * this.DPR * sizeRatio;
|
|
345
431
|
for (const p of this.particles) {
|
|
346
432
|
this.ctx.beginPath();
|
|
347
433
|
this.ctx.arc(p.x, p.y, r, 0, Math.PI * 2);
|
|
@@ -413,9 +499,9 @@ class TextToParticle {
|
|
|
413
499
|
destroy() {
|
|
414
500
|
this.stop();
|
|
415
501
|
this.removeEventListeners();
|
|
416
|
-
if (this.
|
|
417
|
-
this.
|
|
418
|
-
this.
|
|
502
|
+
if (this.visibilityManager) {
|
|
503
|
+
this.visibilityManager.destroy();
|
|
504
|
+
this.visibilityManager = null;
|
|
419
505
|
}
|
|
420
506
|
if (this.canvas && this.canvas.parentNode) {
|
|
421
507
|
this.canvas.parentNode.removeChild(this.canvas);
|
|
@@ -446,54 +532,31 @@ class Count {
|
|
|
446
532
|
this.currentValue = this.config.startValue;
|
|
447
533
|
this.startTime = null;
|
|
448
534
|
this.animationFrameId = null;
|
|
449
|
-
this.
|
|
535
|
+
this.visibilityManager = null;
|
|
450
536
|
this.isRunning = false;
|
|
451
537
|
this.hasTriggered = false;
|
|
452
538
|
this.init();
|
|
453
539
|
}
|
|
454
540
|
init() {
|
|
455
541
|
this.updateDisplay(this.config.startValue);
|
|
456
|
-
this.
|
|
542
|
+
this.setupVisibilityManager();
|
|
457
543
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
(entries) => {
|
|
467
|
-
var _a;
|
|
468
|
-
for (const entry of entries) {
|
|
469
|
-
if (entry.target !== this.container) continue;
|
|
470
|
-
if (entry.isIntersecting) {
|
|
471
|
-
if (!this.hasTriggered && this.config.enabled) {
|
|
472
|
-
this.hasTriggered = true;
|
|
473
|
-
this.start();
|
|
474
|
-
}
|
|
475
|
-
if (this.config.triggerOnce) {
|
|
476
|
-
(_a = this.intersectionObserver) == null ? void 0 : _a.unobserve(this.container);
|
|
477
|
-
}
|
|
478
|
-
} else {
|
|
479
|
-
if (!this.config.triggerOnce) {
|
|
480
|
-
const rect = entry.boundingClientRect;
|
|
481
|
-
const viewportHeight = window.innerHeight;
|
|
482
|
-
const viewportWidth = window.innerWidth;
|
|
483
|
-
const isCompletelyOutOfViewport = rect.bottom <= 0 || rect.top >= viewportHeight || rect.right <= 0 || rect.left >= viewportWidth;
|
|
484
|
-
if (isCompletelyOutOfViewport && this.isRunning) {
|
|
485
|
-
this.reset();
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
}
|
|
544
|
+
setupVisibilityManager() {
|
|
545
|
+
this.visibilityManager = new VisibilityManager(this.container, {
|
|
546
|
+
threshold: this.config.threshold,
|
|
547
|
+
rootMargin: this.config.rootMargin,
|
|
548
|
+
onVisible: () => {
|
|
549
|
+
if (!this.hasTriggered && this.config.enabled) {
|
|
550
|
+
this.hasTriggered = true;
|
|
551
|
+
this.start();
|
|
489
552
|
}
|
|
490
553
|
},
|
|
491
|
-
{
|
|
492
|
-
|
|
493
|
-
|
|
554
|
+
onHidden: () => {
|
|
555
|
+
if (!this.config.triggerOnce && this.isRunning) {
|
|
556
|
+
this.reset();
|
|
557
|
+
}
|
|
494
558
|
}
|
|
495
|
-
);
|
|
496
|
-
this.intersectionObserver.observe(this.container);
|
|
559
|
+
});
|
|
497
560
|
}
|
|
498
561
|
start() {
|
|
499
562
|
if (this.isRunning) return;
|
|
@@ -577,9 +640,9 @@ class Count {
|
|
|
577
640
|
// 파괴 및 정리
|
|
578
641
|
destroy() {
|
|
579
642
|
this.stop();
|
|
580
|
-
if (this.
|
|
581
|
-
this.
|
|
582
|
-
this.
|
|
643
|
+
if (this.visibilityManager) {
|
|
644
|
+
this.visibilityManager.destroy();
|
|
645
|
+
this.visibilityManager = null;
|
|
583
646
|
}
|
|
584
647
|
}
|
|
585
648
|
}
|
|
@@ -669,44 +732,28 @@ class Typing {
|
|
|
669
732
|
this.currentIndex = 0;
|
|
670
733
|
this.displayedText = "";
|
|
671
734
|
this.timeoutId = null;
|
|
672
|
-
this.
|
|
735
|
+
this.visibilityManager = null;
|
|
673
736
|
this.isRunning = false;
|
|
674
737
|
this.hasTriggered = false;
|
|
675
738
|
this.init();
|
|
676
739
|
}
|
|
677
740
|
init() {
|
|
678
741
|
this.updateDisplay("");
|
|
679
|
-
this.
|
|
742
|
+
this.setupVisibilityManager();
|
|
680
743
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
(entries) => {
|
|
690
|
-
var _a;
|
|
691
|
-
for (const entry of entries) {
|
|
692
|
-
if (entry.target !== this.container) continue;
|
|
693
|
-
if (entry.isIntersecting && !this.hasTriggered) {
|
|
694
|
-
if (this.config.enabled) {
|
|
695
|
-
setTimeout(() => this.start(), this.config.delay);
|
|
696
|
-
}
|
|
697
|
-
this.hasTriggered = true;
|
|
698
|
-
if (this.config.triggerOnce) {
|
|
699
|
-
(_a = this.intersectionObserver) == null ? void 0 : _a.disconnect();
|
|
700
|
-
}
|
|
701
|
-
}
|
|
744
|
+
setupVisibilityManager() {
|
|
745
|
+
this.visibilityManager = new VisibilityManager(this.container, {
|
|
746
|
+
threshold: this.config.threshold,
|
|
747
|
+
rootMargin: this.config.rootMargin,
|
|
748
|
+
onVisible: () => {
|
|
749
|
+
if (!this.hasTriggered && this.config.enabled) {
|
|
750
|
+
this.hasTriggered = true;
|
|
751
|
+
setTimeout(() => this.start(), this.config.delay);
|
|
702
752
|
}
|
|
703
753
|
},
|
|
704
|
-
{
|
|
705
|
-
threshold: this.config.threshold,
|
|
706
|
-
rootMargin: this.config.rootMargin
|
|
754
|
+
onHidden: () => {
|
|
707
755
|
}
|
|
708
|
-
);
|
|
709
|
-
this.intersectionObserver.observe(this.container);
|
|
756
|
+
});
|
|
710
757
|
}
|
|
711
758
|
// 단위들을 다시 합쳐서 실제 표시할 텍스트 생성
|
|
712
759
|
// 한글의 경우 자음/모음이 하나씩 보이도록 합성
|
|
@@ -802,9 +849,9 @@ class Typing {
|
|
|
802
849
|
}
|
|
803
850
|
destroy() {
|
|
804
851
|
this.stop();
|
|
805
|
-
if (this.
|
|
806
|
-
this.
|
|
807
|
-
this.
|
|
852
|
+
if (this.visibilityManager) {
|
|
853
|
+
this.visibilityManager.destroy();
|
|
854
|
+
this.visibilityManager = null;
|
|
808
855
|
}
|
|
809
856
|
}
|
|
810
857
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const t=require("vue");function e(t,e){let i=null;return function(...s){null!==i&&clearTimeout(i),i=setTimeout(()=>{i=null,t.apply(this,s)},e)}}class i{constructor(t,i={}){if(this.container="string"==typeof t?document.querySelector(t):t,!this.container)throw new Error("Container element not found");this.config={text:i.text||"mason effect",densityStep:i.densityStep??2,maxParticles:i.maxParticles??3200,pointSize:i.pointSize??.5,ease:i.ease??.05,repelRadius:i.repelRadius??150,repelStrength:i.repelStrength??1,particleColor:i.particleColor||"#fff",fontFamily:i.fontFamily||"Inter, system-ui, Arial",fontSize:i.fontSize||null,width:i.width||null,height:i.height||null,devicePixelRatio:i.devicePixelRatio??null,onReady:i.onReady||null,onUpdate:i.onUpdate||null},this.canvas=document.createElement("canvas");const s=this.canvas.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Canvas context not available");this.ctx=s,this.container.appendChild(this.canvas),this.canvas.style.display="block",this.offCanvas=document.createElement("canvas");const n=this.offCanvas.getContext("2d",{willReadFrequently:!0});if(!n)throw new Error("Offscreen canvas context not available");this.offCtx=n,this.W=0,this.H=0,this.DPR=this.config.devicePixelRatio||Math.min(window.devicePixelRatio||1,1.8),this.particles=[],this.mouse={x:0,y:0,down:!1},this.animationId=null,this.isRunning=!1,this.isVisible=!1,this.intersectionObserver=null,this.debounceDelay=i.debounceDelay??150;const o=this.handleResize.bind(this);this.handleResize=e(o,this.debounceDelay),this.handleMouseMove=this.handleMouseMove.bind(this),this.handleMouseLeave=this.handleMouseLeave.bind(this),this.handleMouseDown=this.handleMouseDown.bind(this),this.handleMouseUp=this.handleMouseUp.bind(this),this._debouncedMorph=e(this._morphInternal.bind(this),this.debounceDelay),this._debouncedUpdateConfig=e(this._updateConfigInternal.bind(this),this.debounceDelay),this.init()}init(){this.resize(),this.setupEventListeners(),this.setupIntersectionObserver(),this.config.onReady&&this.config.onReady(this)}setupIntersectionObserver(){if("undefined"==typeof window||void 0===window.IntersectionObserver)return this.isVisible=!0,void this.start();this.intersectionObserver||(this.intersectionObserver=new IntersectionObserver(t=>{for(const e of t)e.target===this.container&&(e.isIntersecting?(this.isVisible=!0,this.start()):(this.isVisible=!1,this.stop()))},{threshold:.1}),this.intersectionObserver.observe(this.container))}resize(){const t=this.config.width||this.container.clientWidth||window.innerWidth,e=this.config.height||this.container.clientHeight||.7*window.innerHeight;if(t<=0||e<=0)return;this.W=Math.floor(t*this.DPR),this.H=Math.floor(e*this.DPR);const i=4096;if(this.W>i||this.H>i){const t=Math.min(i/this.W,i/this.H);this.W=Math.floor(this.W*t),this.H=Math.floor(this.H*t),this.DPR=this.DPR*t}this.canvas.width=this.W,this.canvas.height=this.H,this.canvas.style.width=t+"px",this.canvas.style.height=e+"px",this.W>0&&this.H>0&&(this.buildTargets(),this.particles.length||this.initParticles())}measureTextFit(t,e,i,s){this.offCtx.font=`400 ${t}px ${this.config.fontFamily}`;const n=e.split("\n"),o=t,h=.1*t,a=.05*t;let l=0;for(const d of n){if(0===d.length)continue;const t=this.offCtx.measureText(d).width+a*(d.length>0?d.length-1:0);l=Math.max(l,t)}const r=n.length>0?o*n.length+h*(n.length-1):o;return{width:l,height:r,fits:l<=i&&r<=s}}findOptimalFontSize(t,e,i,s){if(this.measureTextFit(s,t,e,i).fits)return s;if(s<=12)return 12;let n=12,o=s,h=12;for(;n<=o;){const s=Math.floor((n+o)/2);this.measureTextFit(s,t,e,i).fits?(h=s,n=s+1):o=s-1}return h}buildTargets(){if(this.W<=0||this.H<=0)return;const t=this.config.text;this.offCanvas.width=this.W,this.offCanvas.height=this.H,this.offCtx.clearRect(0,0,this.offCanvas.width,this.offCanvas.height);const e=Math.min(this.W,this.H),i=this.config.fontSize||Math.max(80,Math.floor(.18*e)),s=this.W-80,n=this.H-80,o=this.findOptimalFontSize(t,s,n,i);this.offCtx.fillStyle="#ffffff",this.offCtx.textAlign="center",this.offCtx.textBaseline="middle",this.offCtx.font=`400 ${o}px ${this.config.fontFamily}`;const h=t.split("\n"),a=o,l=.1*o,r=.05*o,d=h.length>0?a*h.length+l*(h.length-1):a;let c=this.H/2-d/2+a/2;for(const m of h){if(0===m.length){c+=a+l;continue}const t=m.split(""),e=this.offCtx.measureText(m).width+r*(t.length>0?t.length-1:0);let i=this.W/2-e/2;for(const s of t)this.offCtx.fillText(s,i+this.offCtx.measureText(s).width/2,c),i+=this.offCtx.measureText(s).width+r;c+=a+l}const f=Math.max(2,this.config.densityStep),u=this.offCtx.getImageData(0,0,this.W,this.H).data,p=[];for(let m=0;m<this.H;m+=f)for(let t=0;t<this.W;t+=f){const e=4*(m*this.W+t);u[e]+u[e+1]+u[e+2]>600&&p.push({x:t,y:m})}for(;p.length>this.config.maxParticles;)p.splice(Math.floor(Math.random()*p.length),1);if(this.particles.length<p.length){const t=p.length-this.particles.length;for(let e=0;e<t;e++)this.particles.push(this.makeParticle())}else this.particles.length>p.length&&(this.particles.length=p.length);for(let m=0;m<this.particles.length;m++){const t=this.particles[m],e=p[m];t.tx=e.x,t.ty=e.y}}makeParticle(){const t=Math.random()*this.W,e=Math.random()*this.H;return{x:t,y:e,vx:0,vy:0,tx:t,ty:e,initialX:t,initialY:e,j:Math.random()*Math.PI*2}}initParticles(){for(const t of this.particles){const e=Math.random()*this.W,i=Math.random()*this.H;t.x=e,t.y=i,t.vx=t.vy=0,t.initialX=e,t.initialY=i}}scatter(){for(const t of this.particles)void 0!==t.initialX&&void 0!==t.initialY?(t.tx=t.initialX,t.ty=t.initialY):(t.initialX=t.x,t.initialY=t.y,t.tx=t.initialX,t.ty=t.initialY)}morph(t){this._debouncedMorph(t)}_morphInternal(t){if(0!==this.W&&0!==this.H||this.resize(),"string"==typeof t)this.config.text=t,this.buildTargets();else if(t&&"object"==typeof t){const e=void 0!==t.text;this.config={...this.config,...t},e&&this.buildTargets()}else this.buildTargets()}update(){this.ctx.clearRect(0,0,this.W,this.H);for(const e of this.particles){let t=(e.tx-e.x)*this.config.ease,i=(e.ty-e.y)*this.config.ease;if(this.mouse.x||this.mouse.y){const s=e.x-this.mouse.x,n=e.y-this.mouse.y,o=s*s+n*n,h=this.config.repelRadius*this.DPR;if(o<h*h){const e=Math.sqrt(o)+1e-4,a=(this.mouse.down?-1:1)*this.config.repelStrength*(1-e/h);t+=s/e*a*6,i+=n/e*a*6}}e.j+=2,t+=.05*Math.cos(e.j),i+=.05*Math.sin(1.3*e.j),e.vx=(e.vx+t)*Math.random(),e.vy=(e.vy+i)*Math.random(),e.x+=e.vx,e.y+=e.vy}this.ctx.fillStyle=this.config.particleColor;const t=this.config.pointSize*this.DPR;for(const e of this.particles)this.ctx.beginPath(),this.ctx.arc(e.x,e.y,t,0,2*Math.PI),this.ctx.fill();this.config.onUpdate&&this.config.onUpdate(this)}animate(){this.isRunning&&(this.update(),this.animationId=requestAnimationFrame(()=>this.animate()))}start(){this.isRunning||(this.isRunning=!0,this.animate())}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}setupEventListeners(){window.addEventListener("resize",this.handleResize),this.canvas.addEventListener("mousemove",this.handleMouseMove),this.canvas.addEventListener("mouseleave",this.handleMouseLeave),this.canvas.addEventListener("mousedown",this.handleMouseDown),window.addEventListener("mouseup",this.handleMouseUp)}removeEventListeners(){window.removeEventListener("resize",this.handleResize),this.canvas.removeEventListener("mousemove",this.handleMouseMove),this.canvas.removeEventListener("mouseleave",this.handleMouseLeave),this.canvas.removeEventListener("mousedown",this.handleMouseDown),window.removeEventListener("mouseup",this.handleMouseUp)}handleResize(){this.resize()}handleMouseMove(t){const e=this.canvas.getBoundingClientRect();this.mouse.x=(t.clientX-e.left)*this.DPR,this.mouse.y=(t.clientY-e.top)*this.DPR}handleMouseLeave(){this.mouse.x=this.mouse.y=0}handleMouseDown(){this.mouse.down=!0}handleMouseUp(){this.mouse.down=!1}updateConfig(t){this._debouncedUpdateConfig(t)}_updateConfigInternal(t){this.config={...this.config,...t},t.text&&this.buildTargets()}destroy(){this.stop(),this.removeEventListeners(),this.intersectionObserver&&(this.intersectionObserver.disconnect(),this.intersectionObserver=null),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}const s=t.defineComponent({__name:"TextToParticle",props:{className:{default:""},style:{default:()=>({})},text:{default:"mason effect"},densityStep:{default:2},maxParticles:{default:3200},pointSize:{default:.5},ease:{default:.05},repelRadius:{default:150},repelStrength:{default:1},particleColor:{default:"#fff"},fontFamily:{default:"Inter, system-ui, Arial"},fontSize:{default:null},width:{default:null},height:{default:null},devicePixelRatio:{default:null},debounceDelay:{},onReady:{type:Function,default:null},onUpdate:{type:Function,default:null}},emits:["ready","update"],setup(e,{expose:s,emit:n}){const o=e,h=n,a=t.ref(null);let l=null;return t.watch(()=>[o.text,o.densityStep,o.maxParticles,o.pointSize,o.ease,o.repelRadius,o.repelStrength,o.particleColor,o.fontFamily,o.fontSize,o.width,o.height,o.devicePixelRatio],()=>{l&&l.updateConfig({text:o.text,densityStep:o.densityStep,maxParticles:o.maxParticles,pointSize:o.pointSize,ease:o.ease,repelRadius:o.repelRadius,repelStrength:o.repelStrength,particleColor:o.particleColor,fontFamily:o.fontFamily,fontSize:o.fontSize,width:o.width,height:o.height,devicePixelRatio:o.devicePixelRatio})}),t.onMounted(()=>{(()=>{if(!a.value)return;const t={text:o.text,densityStep:o.densityStep,maxParticles:o.maxParticles,pointSize:o.pointSize,ease:o.ease,repelRadius:o.repelRadius,repelStrength:o.repelStrength,particleColor:o.particleColor,fontFamily:o.fontFamily,fontSize:o.fontSize,width:o.width,height:o.height,devicePixelRatio:o.devicePixelRatio,onReady:t=>{o.onReady&&o.onReady(t),h("ready",t)},onUpdate:t=>{o.onUpdate&&o.onUpdate(t),h("update",t)}};l=new i(a.value,t)})()}),t.onBeforeUnmount(()=>{l&&(l.destroy(),l=null)}),s({morph:t=>{l&&l.morph(t)},scatter:()=>{l&&l.scatter()},updateConfig:t=>{l&&l.updateConfig(t)},destroy:()=>{l&&(l.destroy(),l=null)}}),(i,s)=>(t.openBlock(),t.createElementBlock("div",{ref_key:"container",ref:a,class:t.normalizeClass(e.className),style:t.normalizeStyle(e.style)},null,6))}});module.exports=s;
|
|
1
|
+
"use strict";const t=require("vue");class i{constructor(t,i={}){this.container=t,this.options={threshold:i.threshold??.1,rootMargin:i.rootMargin??"0px",onVisible:i.onVisible,onHidden:i.onHidden},this.intersectionObserver=null,this.visibilityChangeHandler=null,this.isVisible=!1,this.isPageVisible="undefined"==typeof document||!document.hidden,this.setupIntersectionObserver(),this.setupPageVisibility()}setupIntersectionObserver(){if("undefined"==typeof window||void 0===window.IntersectionObserver)return this.isVisible=!0,void(this.isPageVisible&&this.options.onVisible&&this.options.onVisible());this.intersectionObserver=new IntersectionObserver(t=>{for(const i of t)i.target===this.container&&(i.isIntersecting?(this.isVisible=!0,this.isPageVisible&&this.options.onVisible&&this.options.onVisible()):(this.isVisible=!1,this.options.onHidden&&this.options.onHidden()))},{threshold:this.options.threshold,rootMargin:this.options.rootMargin}),this.intersectionObserver.observe(this.container)}setupPageVisibility(){"undefined"!=typeof document&&(this.visibilityChangeHandler=()=>{const t=this.isPageVisible;this.isPageVisible=!document.hidden,document.hidden?this.options.onHidden&&this.options.onHidden():t!==this.isPageVisible&&this.isVisible&&this.options.onVisible&&this.options.onVisible()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),document.hidden&&this.isVisible&&this.options.onHidden&&this.options.onHidden())}getIsVisible(){return this.isVisible&&this.isPageVisible}updateOptions(t){this.options={...this.options,...t},this.intersectionObserver&&(this.intersectionObserver.disconnect(),this.intersectionObserver=null),this.setupIntersectionObserver()}destroy(){this.intersectionObserver&&(this.intersectionObserver.disconnect(),this.intersectionObserver=null),this.visibilityChangeHandler&&"undefined"!=typeof document&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null)}}function e(t,i){let e=null;return function(...s){null!==e&&clearTimeout(e),e=setTimeout(()=>{e=null,t.apply(this,s)},i)}}class s{constructor(t,i={}){if(this.container="string"==typeof t?document.querySelector(t):t,!this.container)throw new Error("Container element not found");this.config={text:i.text||"mason effect",densityStep:i.densityStep??2,maxParticles:i.maxParticles??3200,pointSize:i.pointSize??.5,ease:i.ease??.05,repelRadius:i.repelRadius??150,repelStrength:i.repelStrength??1,particleColor:i.particleColor||"#fff",fontFamily:i.fontFamily||"Inter, system-ui, Arial",fontSize:i.fontSize||null,width:i.width||null,height:i.height||null,devicePixelRatio:i.devicePixelRatio??null,onReady:i.onReady||null,onUpdate:i.onUpdate||null},this.canvas=document.createElement("canvas");const s=this.canvas.getContext("2d",{willReadFrequently:!0});if(!s)throw new Error("Canvas context not available");this.ctx=s,this.container.appendChild(this.canvas),this.canvas.style.display="block",this.offCanvas=document.createElement("canvas");const n=this.offCanvas.getContext("2d",{willReadFrequently:!0});if(!n)throw new Error("Offscreen canvas context not available");this.offCtx=n,this.W=0,this.H=0,this.DPR=this.config.devicePixelRatio||Math.min(window.devicePixelRatio||1,1.8),this.particles=[],this.mouse={x:0,y:0,down:!1},this.animationId=null,this.isRunning=!1,this.visibilityManager=null,this.debounceDelay=i.debounceDelay??150;const o=this.handleResize.bind(this);this.handleResize=e(o,this.debounceDelay),this.handleMouseMove=this.handleMouseMove.bind(this),this.handleMouseLeave=this.handleMouseLeave.bind(this),this.handleMouseDown=this.handleMouseDown.bind(this),this.handleMouseUp=this.handleMouseUp.bind(this),this._debouncedMorph=e(this._morphInternal.bind(this),this.debounceDelay),this._debouncedUpdateConfig=e(this._updateConfigInternal.bind(this),this.debounceDelay),this.init()}init(){this.resize(),this.setupEventListeners(),this.setupVisibilityManager(),this.config.onReady&&this.config.onReady(this)}setupVisibilityManager(){this.visibilityManager=new i(this.container,{threshold:.1,onVisible:()=>{this.start()},onHidden:()=>{this.stop()}})}resize(){const t=this.config.width||this.container.clientWidth||window.innerWidth,i=this.config.height||this.container.clientHeight||.7*window.innerHeight;if(t<=0||i<=0)return;this.W=Math.floor(t*this.DPR),this.H=Math.floor(i*this.DPR);const e=4096;if(this.W>e||this.H>e){const t=Math.min(e/this.W,e/this.H);this.W=Math.floor(this.W*t),this.H=Math.floor(this.H*t),this.DPR=this.DPR*t}this.canvas.width=this.W,this.canvas.height=this.H,this.canvas.style.width=t+"px",this.canvas.style.height=i+"px",this.W>0&&this.H>0&&(this.buildTargets(),this.particles.length||this.initParticles())}measureTextFit(t,i,e,s){this.offCtx.font=`400 ${t}px ${this.config.fontFamily}`;const n=i.split("\n"),o=t,h=.1*t,a=.05*t;let l=0;for(const d of n){if(0===d.length)continue;const t=this.offCtx.measureText(d).width+a*(d.length>0?d.length-1:0);l=Math.max(l,t)}const r=n.length>0?o*n.length+h*(n.length-1):o;return{width:l,height:r,fits:l<=e&&r<=s}}findOptimalFontSize(t,i,e,s){if(this.measureTextFit(s,t,i,e).fits)return s;if(s<=12)return 12;let n=12,o=s,h=12;for(;n<=o;){const s=Math.floor((n+o)/2);this.measureTextFit(s,t,i,e).fits?(h=s,n=s+1):o=s-1}return h}buildTargets(){if(this.W<=0||this.H<=0)return;const t=this.config.text;this.offCanvas.width=this.W,this.offCanvas.height=this.H,this.offCtx.clearRect(0,0,this.offCanvas.width,this.offCanvas.height);const i=Math.min(this.W,this.H),e=this.config.fontSize||Math.max(80,Math.floor(.18*i)),s=this.W-80,n=this.H-80,o=this.findOptimalFontSize(t,s,n,e);this.offCtx.fillStyle="#ffffff",this.offCtx.textAlign="center",this.offCtx.textBaseline="middle",this.offCtx.font=`400 ${o}px ${this.config.fontFamily}`;const h=t.split("\n"),a=o,l=.1*o,r=.05*o,d=h.length>0?a*h.length+l*(h.length-1):a;let c=this.H/2-d/2+a/2;for(const g of h){if(0===g.length){c+=a+l;continue}const t=g.split(""),i=this.offCtx.measureText(g).width+r*(t.length>0?t.length-1:0);let e=this.W/2-i/2;for(const s of t)this.offCtx.fillText(s,e+this.offCtx.measureText(s).width/2,c),e+=this.offCtx.measureText(s).width+r;c+=a+l}const f=Math.max(2,this.config.densityStep),u=this.offCtx.getImageData(0,0,this.W,this.H).data,p=[];for(let g=0;g<this.H;g+=f)for(let t=0;t<this.W;t+=f){const i=4*(g*this.W+t);u[i]+u[i+1]+u[i+2]>600&&p.push({x:t,y:g})}for(;p.length>this.config.maxParticles;)p.splice(Math.floor(Math.random()*p.length),1);if(this.particles.length<p.length){const t=p.length-this.particles.length;for(let i=0;i<t;i++)this.particles.push(this.makeParticle())}else this.particles.length>p.length&&(this.particles.length=p.length);for(let g=0;g<this.particles.length;g++){const t=this.particles[g],i=p[g];t.tx=i.x,t.ty=i.y}}makeParticle(){const t=Math.random()*this.W,i=Math.random()*this.H;return{x:t,y:i,vx:0,vy:0,tx:t,ty:i,initialX:t,initialY:i,j:Math.random()*Math.PI*2}}initParticles(){for(const t of this.particles){const i=Math.random()*this.W,e=Math.random()*this.H;t.x=i,t.y=e,t.vx=t.vy=0,t.initialX=i,t.initialY=e}}scatter(){for(const t of this.particles)void 0!==t.initialX&&void 0!==t.initialY?(t.tx=t.initialX,t.ty=t.initialY):(t.initialX=t.x,t.initialY=t.y,t.tx=t.initialX,t.ty=t.initialY)}morph(t){this._debouncedMorph(t)}_morphInternal(t){if(0!==this.W&&0!==this.H||this.resize(),"string"==typeof t)this.config.text=t,this.buildTargets();else if(t&&"object"==typeof t){const i=void 0!==t.text;this.config={...this.config,...t},i&&this.buildTargets()}else this.buildTargets()}update(){this.ctx.clearRect(0,0,this.W,this.H);for(const s of this.particles){let t=(s.tx-s.x)*this.config.ease,i=(s.ty-s.y)*this.config.ease;if(this.mouse.x||this.mouse.y){const e=s.x-this.mouse.x,n=s.y-this.mouse.y,o=e*e+n*n,h=this.config.repelRadius*this.DPR;if(o<h*h){const s=Math.sqrt(o)+1e-4,a=(this.mouse.down?-1:1)*this.config.repelStrength*(1-s/h);t+=e/s*a*6,i+=n/s*a*6}}s.j+=2,t+=.05*Math.cos(s.j),i+=.05*Math.sin(1.3*s.j),s.vx=(s.vx+t)*Math.random(),s.vy=(s.vy+i)*Math.random(),s.x+=s.vx,s.y+=s.vy}this.ctx.fillStyle=this.config.particleColor;const t=Math.min(this.W,this.H)/this.DPR,i=Math.max(.5,Math.min(2,t/1920)),e=this.config.pointSize*this.DPR*i;for(const s of this.particles)this.ctx.beginPath(),this.ctx.arc(s.x,s.y,e,0,2*Math.PI),this.ctx.fill();this.config.onUpdate&&this.config.onUpdate(this)}animate(){this.isRunning&&(this.update(),this.animationId=requestAnimationFrame(()=>this.animate()))}start(){this.isRunning||(this.isRunning=!0,this.animate())}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}setupEventListeners(){window.addEventListener("resize",this.handleResize),this.canvas.addEventListener("mousemove",this.handleMouseMove),this.canvas.addEventListener("mouseleave",this.handleMouseLeave),this.canvas.addEventListener("mousedown",this.handleMouseDown),window.addEventListener("mouseup",this.handleMouseUp)}removeEventListeners(){window.removeEventListener("resize",this.handleResize),this.canvas.removeEventListener("mousemove",this.handleMouseMove),this.canvas.removeEventListener("mouseleave",this.handleMouseLeave),this.canvas.removeEventListener("mousedown",this.handleMouseDown),window.removeEventListener("mouseup",this.handleMouseUp)}handleResize(){this.resize()}handleMouseMove(t){const i=this.canvas.getBoundingClientRect();this.mouse.x=(t.clientX-i.left)*this.DPR,this.mouse.y=(t.clientY-i.top)*this.DPR}handleMouseLeave(){this.mouse.x=this.mouse.y=0}handleMouseDown(){this.mouse.down=!0}handleMouseUp(){this.mouse.down=!1}updateConfig(t){this._debouncedUpdateConfig(t)}_updateConfigInternal(t){this.config={...this.config,...t},t.text&&this.buildTargets()}destroy(){this.stop(),this.removeEventListeners(),this.visibilityManager&&(this.visibilityManager.destroy(),this.visibilityManager=null),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}const n=t.defineComponent({__name:"TextToParticle",props:{className:{default:""},style:{default:()=>({})},text:{default:"mason effect"},densityStep:{default:2},maxParticles:{default:3200},pointSize:{default:.5},ease:{default:.05},repelRadius:{default:150},repelStrength:{default:1},particleColor:{default:"#fff"},fontFamily:{default:"Inter, system-ui, Arial"},fontSize:{default:null},width:{default:null},height:{default:null},devicePixelRatio:{default:null},debounceDelay:{},onReady:{type:Function,default:null},onUpdate:{type:Function,default:null}},emits:["ready","update"],setup(i,{expose:e,emit:n}){const o=i,h=n,a=t.ref(null);let l=null;return t.watch(()=>[o.text,o.densityStep,o.maxParticles,o.pointSize,o.ease,o.repelRadius,o.repelStrength,o.particleColor,o.fontFamily,o.fontSize,o.width,o.height,o.devicePixelRatio],()=>{l&&l.updateConfig({text:o.text,densityStep:o.densityStep,maxParticles:o.maxParticles,pointSize:o.pointSize,ease:o.ease,repelRadius:o.repelRadius,repelStrength:o.repelStrength,particleColor:o.particleColor,fontFamily:o.fontFamily,fontSize:o.fontSize,width:o.width,height:o.height,devicePixelRatio:o.devicePixelRatio})}),t.onMounted(()=>{(()=>{if(!a.value)return;const t={text:o.text,densityStep:o.densityStep,maxParticles:o.maxParticles,pointSize:o.pointSize,ease:o.ease,repelRadius:o.repelRadius,repelStrength:o.repelStrength,particleColor:o.particleColor,fontFamily:o.fontFamily,fontSize:o.fontSize,width:o.width,height:o.height,devicePixelRatio:o.devicePixelRatio,onReady:t=>{o.onReady&&o.onReady(t),h("ready",t)},onUpdate:t=>{o.onUpdate&&o.onUpdate(t),h("update",t)}};l=new s(a.value,t)})()}),t.onBeforeUnmount(()=>{l&&(l.destroy(),l=null)}),e({morph:t=>{l&&l.morph(t)},scatter:()=>{l&&l.scatter()},updateConfig:t=>{l&&l.updateConfig(t)},destroy:()=>{l&&(l.destroy(),l=null)}}),(e,s)=>(t.openBlock(),t.createElementBlock("div",{ref_key:"container",ref:a,class:t.normalizeClass(i.className),style:t.normalizeStyle(i.style)},null,6))}});module.exports=n;
|
|
@@ -7,12 +7,12 @@ export declare class Count {
|
|
|
7
7
|
currentValue: number;
|
|
8
8
|
startTime: number | null;
|
|
9
9
|
animationFrameId: number | null;
|
|
10
|
-
|
|
10
|
+
visibilityManager: VisibilityManager | null;
|
|
11
11
|
isRunning: boolean;
|
|
12
12
|
hasTriggered: boolean;
|
|
13
13
|
constructor(container: HTMLElement | string, options: CountOptions);
|
|
14
14
|
init(): void;
|
|
15
|
-
|
|
15
|
+
setupVisibilityManager(): void;
|
|
16
16
|
start(): void;
|
|
17
17
|
stop(): void;
|
|
18
18
|
reset(): void;
|
|
@@ -23,13 +23,6 @@ export declare class Count {
|
|
|
23
23
|
destroy(): void;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
/**
|
|
27
|
-
* Count - 숫자 카운팅 애니메이션 효과
|
|
28
|
-
* 바닐라 JS 코어 클래스
|
|
29
|
-
*
|
|
30
|
-
* 사용법:
|
|
31
|
-
* import { Count } from 'masoneffect/count';
|
|
32
|
-
*/
|
|
33
26
|
export declare interface CountOptions {
|
|
34
27
|
targetValue: number;
|
|
35
28
|
duration?: number;
|
|
@@ -84,14 +77,13 @@ declare class TextToParticle {
|
|
|
84
77
|
};
|
|
85
78
|
animationId: number | null;
|
|
86
79
|
isRunning: boolean;
|
|
87
|
-
|
|
88
|
-
intersectionObserver: IntersectionObserver | null;
|
|
80
|
+
visibilityManager: VisibilityManager | null;
|
|
89
81
|
debounceDelay: number;
|
|
90
82
|
_debouncedMorph: (textOrOptions?: string | Partial<TextToParticleOptions> | null) => void;
|
|
91
83
|
_debouncedUpdateConfig: (newConfig: Partial<TextToParticleOptions>) => void;
|
|
92
84
|
constructor(container: HTMLElement | string, options?: TextToParticleOptions);
|
|
93
85
|
init(): void;
|
|
94
|
-
|
|
86
|
+
setupVisibilityManager(): void;
|
|
95
87
|
resize(): void;
|
|
96
88
|
/**
|
|
97
89
|
* 텍스트가 영역 안에 들어가는지 확인하는 헬퍼 함수 (줄바꿈 지원)
|
|
@@ -132,13 +124,6 @@ declare class TextToParticle {
|
|
|
132
124
|
export { TextToParticle }
|
|
133
125
|
export default TextToParticle;
|
|
134
126
|
|
|
135
|
-
/**
|
|
136
|
-
* TextToParticle - 텍스트를 파티클로 변환하는 효과
|
|
137
|
-
* 바닐라 JS 코어 클래스
|
|
138
|
-
*
|
|
139
|
-
* 사용법:
|
|
140
|
-
* import { TextToParticle } from 'masoneffect/textToParticle';
|
|
141
|
-
*/
|
|
142
127
|
declare interface TextToParticleOptions {
|
|
143
128
|
text?: string;
|
|
144
129
|
densityStep?: number;
|
|
@@ -175,13 +160,13 @@ declare class TextToParticle {
|
|
|
175
160
|
currentIndex: number;
|
|
176
161
|
displayedText: string;
|
|
177
162
|
timeoutId: ReturnType<typeof setTimeout> | null;
|
|
178
|
-
|
|
163
|
+
visibilityManager: VisibilityManager | null;
|
|
179
164
|
isRunning: boolean;
|
|
180
165
|
hasTriggered: boolean;
|
|
181
166
|
originalText: string;
|
|
182
167
|
constructor(container: HTMLElement | string, options: TypingOptions);
|
|
183
168
|
init(): void;
|
|
184
|
-
|
|
169
|
+
setupVisibilityManager(): void;
|
|
185
170
|
private buildTextFromUnits;
|
|
186
171
|
start(): void;
|
|
187
172
|
typeNext(): void;
|
|
@@ -192,13 +177,6 @@ declare class TextToParticle {
|
|
|
192
177
|
destroy(): void;
|
|
193
178
|
}
|
|
194
179
|
|
|
195
|
-
/**
|
|
196
|
-
* Typing - 타이핑 애니메이션 효과
|
|
197
|
-
* 바닐라 JS 코어 클래스
|
|
198
|
-
*
|
|
199
|
-
* 사용법:
|
|
200
|
-
* import { Typing } from 'masoneffect/typing';
|
|
201
|
-
*/
|
|
202
180
|
export declare interface TypingOptions {
|
|
203
181
|
text: string;
|
|
204
182
|
speed?: number;
|
|
@@ -213,4 +191,39 @@ declare class TextToParticle {
|
|
|
213
191
|
onComplete?: () => void;
|
|
214
192
|
}
|
|
215
193
|
|
|
194
|
+
declare class VisibilityManager {
|
|
195
|
+
private container;
|
|
196
|
+
private options;
|
|
197
|
+
private intersectionObserver;
|
|
198
|
+
private visibilityChangeHandler;
|
|
199
|
+
private isVisible;
|
|
200
|
+
private isPageVisible;
|
|
201
|
+
constructor(container: HTMLElement, options?: VisibilityManagerOptions);
|
|
202
|
+
private setupIntersectionObserver;
|
|
203
|
+
private setupPageVisibility;
|
|
204
|
+
/**
|
|
205
|
+
* 현재 요소가 화면에 보이는지 확인
|
|
206
|
+
*/
|
|
207
|
+
getIsVisible(): boolean;
|
|
208
|
+
/**
|
|
209
|
+
* 옵션 업데이트
|
|
210
|
+
*/
|
|
211
|
+
updateOptions(newOptions: Partial<VisibilityManagerOptions>): void;
|
|
212
|
+
/**
|
|
213
|
+
* 리소스 정리
|
|
214
|
+
*/
|
|
215
|
+
destroy(): void;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* VisibilityManager - IntersectionObserver와 Page Visibility API를 통합 관리
|
|
220
|
+
* 모든 효과에서 공통으로 사용하는 가시성 관리 유틸리티
|
|
221
|
+
*/
|
|
222
|
+
declare interface VisibilityManagerOptions {
|
|
223
|
+
threshold?: number;
|
|
224
|
+
rootMargin?: string;
|
|
225
|
+
onVisible?: () => void;
|
|
226
|
+
onHidden?: () => void;
|
|
227
|
+
}
|
|
228
|
+
|
|
216
229
|
export { }
|