masoneffect 0.1.11 → 0.1.13

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/src/core/index.js CHANGED
@@ -3,6 +3,19 @@
3
3
  * 바닐라 JS 코어 클래스
4
4
  */
5
5
 
6
+ // 디바운스 유틸리티 함수
7
+ function debounce(func, wait) {
8
+ let timeout;
9
+ return function executedFunction(...args) {
10
+ const later = () => {
11
+ clearTimeout(timeout);
12
+ func.apply(this, args);
13
+ };
14
+ clearTimeout(timeout);
15
+ timeout = setTimeout(later, wait);
16
+ };
17
+ }
18
+
6
19
  export class MasonEffect {
7
20
  constructor(container, options = {}) {
8
21
  // 컨테이너 요소
@@ -51,14 +64,24 @@ export class MasonEffect {
51
64
  this.mouse = { x: 0, y: 0, down: false };
52
65
  this.animationId = null;
53
66
  this.isRunning = false;
67
+ this.isVisible = false;
68
+ this.intersectionObserver = null;
54
69
 
55
- // 이벤트 핸들러 바인딩
56
- this.handleResize = this.handleResize.bind(this);
70
+ // 디바운스 설정 (ms)
71
+ this.debounceDelay = options.debounceDelay ?? 150; // 기본 150ms
72
+
73
+ // 이벤트 핸들러 바인딩 (디바운스 적용 전에 바인딩)
74
+ const boundHandleResize = this.handleResize.bind(this);
75
+ this.handleResize = debounce(boundHandleResize, this.debounceDelay);
57
76
  this.handleMouseMove = this.handleMouseMove.bind(this);
58
77
  this.handleMouseLeave = this.handleMouseLeave.bind(this);
59
78
  this.handleMouseDown = this.handleMouseDown.bind(this);
60
79
  this.handleMouseUp = this.handleMouseUp.bind(this);
61
80
 
81
+ // morph와 updateConfig를 위한 디바운스된 내부 메서드
82
+ this._debouncedMorph = debounce(this._morphInternal.bind(this), this.debounceDelay);
83
+ this._debouncedUpdateConfig = debounce(this._updateConfigInternal.bind(this), this.debounceDelay);
84
+
62
85
  // 초기화
63
86
  this.init();
64
87
  }
@@ -66,13 +89,48 @@ export class MasonEffect {
66
89
  init() {
67
90
  this.resize();
68
91
  this.setupEventListeners();
69
- this.start();
70
-
92
+ this.setupIntersectionObserver();
93
+
71
94
  if (this.config.onReady) {
72
95
  this.config.onReady(this);
73
96
  }
74
97
  }
75
98
 
99
+ setupIntersectionObserver() {
100
+ // IntersectionObserver가 지원되지 않는 환경에서는 항상 재생
101
+ if (typeof window === 'undefined' || typeof window.IntersectionObserver === 'undefined') {
102
+ this.isVisible = true;
103
+ this.start();
104
+ return;
105
+ }
106
+
107
+ // 이미 설정되어 있다면 다시 만들지 않음
108
+ if (this.intersectionObserver) {
109
+ return;
110
+ }
111
+
112
+ this.intersectionObserver = new IntersectionObserver(
113
+ (entries) => {
114
+ for (const entry of entries) {
115
+ if (entry.target !== this.container) continue;
116
+
117
+ if (entry.isIntersecting) {
118
+ this.isVisible = true;
119
+ this.start();
120
+ } else {
121
+ this.isVisible = false;
122
+ this.stop();
123
+ }
124
+ }
125
+ },
126
+ {
127
+ threshold: 0.1, // 10% 이상 보일 때 동작
128
+ }
129
+ );
130
+
131
+ this.intersectionObserver.observe(this.container);
132
+ }
133
+
76
134
  resize() {
77
135
  const width = this.config.width || this.container.clientWidth || window.innerWidth;
78
136
  const height = this.config.height || this.container.clientHeight || window.innerHeight * 0.7;
@@ -202,6 +260,12 @@ export class MasonEffect {
202
260
  }
203
261
 
204
262
  morph(textOrOptions = null) {
263
+ // 즉시 실행이 필요한 경우 (예: 초기화 시)를 위해 내부 메서드 직접 호출
264
+ // 일반적인 경우에는 디바운스 적용
265
+ this._debouncedMorph(textOrOptions);
266
+ }
267
+
268
+ _morphInternal(textOrOptions = null) {
205
269
  // W와 H가 0이면 resize 먼저 실행
206
270
  if (this.W === 0 || this.H === 0) {
207
271
  this.resize();
@@ -332,6 +396,11 @@ export class MasonEffect {
332
396
 
333
397
  // 설정 업데이트
334
398
  updateConfig(newConfig) {
399
+ // 디바운스 적용
400
+ this._debouncedUpdateConfig(newConfig);
401
+ }
402
+
403
+ _updateConfigInternal(newConfig) {
335
404
  this.config = { ...this.config, ...newConfig };
336
405
  if (newConfig.text) {
337
406
  this.buildTargets();
@@ -342,6 +411,10 @@ export class MasonEffect {
342
411
  destroy() {
343
412
  this.stop();
344
413
  this.removeEventListeners();
414
+ if (this.intersectionObserver) {
415
+ this.intersectionObserver.disconnect();
416
+ this.intersectionObserver = null;
417
+ }
345
418
  if (this.canvas && this.canvas.parentNode) {
346
419
  this.canvas.parentNode.removeChild(this.canvas);
347
420
  }
package/src/index.js CHANGED
@@ -2,6 +2,12 @@
2
2
  * MasonEffect - 메인 엔트리 포인트
3
3
  */
4
4
 
5
- export { MasonEffect } from './core/index.js';
6
- export { default } from './core/index.js';
5
+ import MasonEffect from './core/index.js';
6
+
7
+ // Named export
8
+ export { MasonEffect };
9
+
10
+ // Default export (UMD 빌드에서 전역 변수로 직접 노출됨)
11
+ // CDN 사용 시: new MasonEffect()로 직접 사용 가능
12
+ export default MasonEffect;
7
13