@digo-org/digo-api 1.0.49 → 1.0.51
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/package.json +1 -1
- package/src/templates/balls.tsx +87 -87
package/package.json
CHANGED
package/src/templates/balls.tsx
CHANGED
|
@@ -52,16 +52,16 @@ interface SizeData {
|
|
|
52
52
|
|
|
53
53
|
class X {
|
|
54
54
|
// Private fields
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
private config: XConfig;
|
|
56
|
+
private _postprocessing: any;
|
|
57
|
+
private resizeObserver?: ResizeObserver;
|
|
58
|
+
private intersectionObserver?: IntersectionObserver;
|
|
59
|
+
private resizeTimer?: number;
|
|
60
|
+
private animationFrameId: number = 0;
|
|
61
|
+
private clock: Clock = new Clock();
|
|
62
|
+
private animationState = { elapsed: 0, delta: 0 };
|
|
63
|
+
private isAnimating: boolean = false;
|
|
64
|
+
private isVisible: boolean = false;
|
|
65
65
|
|
|
66
66
|
canvas!: HTMLCanvasElement;
|
|
67
67
|
camera!: PerspectiveCamera;
|
|
@@ -81,7 +81,7 @@ class X {
|
|
|
81
81
|
pixelRatio: 0,
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
-
render: () => void = this
|
|
84
|
+
// render: () => void = this.render.bind(this);
|
|
85
85
|
|
|
86
86
|
onBeforeRender: (state: { elapsed: number; delta: number; }) => void =
|
|
87
87
|
() => {};
|
|
@@ -91,28 +91,28 @@ class X {
|
|
|
91
91
|
isDisposed: boolean = false;
|
|
92
92
|
|
|
93
93
|
constructor(config: XConfig) {
|
|
94
|
-
this
|
|
95
|
-
this
|
|
96
|
-
this
|
|
97
|
-
this
|
|
94
|
+
this.config = { ...config };
|
|
95
|
+
this.initCamera();
|
|
96
|
+
this.initScene();
|
|
97
|
+
this.initRenderer();
|
|
98
98
|
this.resize();
|
|
99
|
-
this
|
|
99
|
+
this.initObservers();
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
private initCamera() {
|
|
103
103
|
this.camera = new PerspectiveCamera();
|
|
104
104
|
this.cameraFov = this.camera.fov;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
private initScene() {
|
|
108
108
|
this.scene = new Scene();
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
if (this
|
|
113
|
-
this.canvas = this
|
|
114
|
-
} else if (this
|
|
115
|
-
const elem = document.getElementById(this
|
|
111
|
+
private initRenderer() {
|
|
112
|
+
if (this.config.canvas) {
|
|
113
|
+
this.canvas = this.config.canvas;
|
|
114
|
+
} else if (this.config.id) {
|
|
115
|
+
const elem = document.getElementById(this.config.id);
|
|
116
116
|
if (elem instanceof HTMLCanvasElement) {
|
|
117
117
|
this.canvas = elem;
|
|
118
118
|
} else {
|
|
@@ -125,42 +125,42 @@ class X {
|
|
|
125
125
|
const rendererOptions: WebGLRendererParameters = {
|
|
126
126
|
canvas: this.canvas,
|
|
127
127
|
powerPreference: 'high-performance',
|
|
128
|
-
...(this
|
|
128
|
+
...(this.config.rendererOptions ?? {}),
|
|
129
129
|
};
|
|
130
130
|
this.renderer = new WebGLRenderer(rendererOptions);
|
|
131
131
|
this.renderer.outputColorSpace = SRGBColorSpace;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
|
|
135
|
-
if (!(this
|
|
136
|
-
window.addEventListener('resize', this
|
|
137
|
-
if (this
|
|
138
|
-
this
|
|
139
|
-
this
|
|
134
|
+
private initObservers() {
|
|
135
|
+
if (!(this.config.size instanceof Object)) {
|
|
136
|
+
window.addEventListener('resize', this.onResize.bind(this));
|
|
137
|
+
if (this.config.size === 'parent' && this.canvas.parentNode) {
|
|
138
|
+
this.resizeObserver = new ResizeObserver(this.onResize.bind(this));
|
|
139
|
+
this.resizeObserver.observe(this.canvas.parentNode as Element);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
-
this
|
|
143
|
-
this
|
|
142
|
+
this.intersectionObserver = new IntersectionObserver(
|
|
143
|
+
this.onIntersection.bind(this),
|
|
144
144
|
{ root: null, rootMargin: '0px', threshold: 0 },
|
|
145
145
|
);
|
|
146
|
-
this
|
|
146
|
+
this.intersectionObserver.observe(this.canvas);
|
|
147
147
|
document.addEventListener(
|
|
148
148
|
'visibilitychange',
|
|
149
|
-
this
|
|
149
|
+
this.onVisibilityChange.bind(this),
|
|
150
150
|
);
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
|
|
154
|
-
if (this
|
|
155
|
-
this
|
|
153
|
+
private onResize() {
|
|
154
|
+
if (this.resizeTimer) clearTimeout(this.resizeTimer);
|
|
155
|
+
this.resizeTimer = window.setTimeout(this.resize.bind(this), 100);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
resize() {
|
|
159
159
|
let w: number, h: number;
|
|
160
|
-
if (this
|
|
161
|
-
w = this
|
|
162
|
-
h = this
|
|
163
|
-
} else if (this
|
|
160
|
+
if (this.config.size instanceof Object) {
|
|
161
|
+
w = this.config.size.width;
|
|
162
|
+
h = this.config.size.height;
|
|
163
|
+
} else if (this.config.size === 'parent' && this.canvas.parentNode) {
|
|
164
164
|
w = (this.canvas.parentNode as HTMLElement).offsetWidth;
|
|
165
165
|
h = (this.canvas.parentNode as HTMLElement).offsetHeight;
|
|
166
166
|
} else {
|
|
@@ -170,21 +170,21 @@ class X {
|
|
|
170
170
|
this.size.width = w;
|
|
171
171
|
this.size.height = h;
|
|
172
172
|
this.size.ratio = w / h;
|
|
173
|
-
this
|
|
174
|
-
this
|
|
173
|
+
this.updateCamera();
|
|
174
|
+
this.updateRenderer();
|
|
175
175
|
this.onAfterResize(this.size);
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
|
|
178
|
+
private updateCamera() {
|
|
179
179
|
this.camera.aspect = this.size.width / this.size.height;
|
|
180
180
|
if (this.camera.isPerspectiveCamera && this.cameraFov) {
|
|
181
181
|
if (this.cameraMinAspect && this.camera.aspect < this.cameraMinAspect) {
|
|
182
|
-
this
|
|
182
|
+
this.adjustFov(this.cameraMinAspect);
|
|
183
183
|
} else if (
|
|
184
184
|
this.cameraMaxAspect &&
|
|
185
185
|
this.camera.aspect > this.cameraMaxAspect
|
|
186
186
|
) {
|
|
187
|
-
this
|
|
187
|
+
this.adjustFov(this.cameraMaxAspect);
|
|
188
188
|
} else {
|
|
189
189
|
this.camera.fov = this.cameraFov;
|
|
190
190
|
}
|
|
@@ -193,7 +193,7 @@ class X {
|
|
|
193
193
|
this.updateWorldSize();
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
|
|
196
|
+
private adjustFov(aspect: number) {
|
|
197
197
|
const tanFov = Math.tan(MathUtils.degToRad(this.cameraFov / 2));
|
|
198
198
|
const newTan = tanFov / (this.camera.aspect / aspect);
|
|
199
199
|
this.camera.fov = 2 * MathUtils.radToDeg(Math.atan(newTan));
|
|
@@ -212,9 +212,9 @@ class X {
|
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
-
|
|
215
|
+
private updateRenderer() {
|
|
216
216
|
this.renderer.setSize(this.size.width, this.size.height);
|
|
217
|
-
this
|
|
217
|
+
this._postprocessing?.setSize(this.size.width, this.size.height);
|
|
218
218
|
let pr = window.devicePixelRatio;
|
|
219
219
|
if (this.maxPixelRatio && pr > this.maxPixelRatio) {
|
|
220
220
|
pr = this.maxPixelRatio;
|
|
@@ -226,57 +226,57 @@ class X {
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
get postprocessing() {
|
|
229
|
-
return this
|
|
229
|
+
return this._postprocessing;
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
set postprocessing(value: any) {
|
|
233
|
-
this
|
|
233
|
+
this._postprocessing = value;
|
|
234
234
|
this.render = value.render.bind(value);
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
|
|
238
|
-
this
|
|
239
|
-
if (this
|
|
240
|
-
this
|
|
237
|
+
private onIntersection(entries: IntersectionObserverEntry[]) {
|
|
238
|
+
this.isAnimating = entries[0].isIntersecting;
|
|
239
|
+
if (this.isAnimating) {
|
|
240
|
+
this.startAnimation();
|
|
241
241
|
} else {
|
|
242
|
-
this
|
|
242
|
+
this.stopAnimation();
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
-
|
|
247
|
-
if (this
|
|
246
|
+
private onVisibilityChange() {
|
|
247
|
+
if (this.isAnimating) {
|
|
248
248
|
if (document.hidden) {
|
|
249
|
-
this
|
|
249
|
+
this.stopAnimation();
|
|
250
250
|
} else {
|
|
251
|
-
this
|
|
251
|
+
this.startAnimation();
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
|
|
257
|
-
if (this
|
|
256
|
+
private startAnimation() {
|
|
257
|
+
if (this.isVisible) return;
|
|
258
258
|
const animateFrame = () => {
|
|
259
|
-
this
|
|
260
|
-
this
|
|
261
|
-
this
|
|
262
|
-
this.onBeforeRender(this
|
|
259
|
+
this.animationFrameId = requestAnimationFrame(animateFrame);
|
|
260
|
+
this.animationState.delta = this.clock.getDelta();
|
|
261
|
+
this.animationState.elapsed += this.animationState.delta;
|
|
262
|
+
this.onBeforeRender(this.animationState);
|
|
263
263
|
this.render();
|
|
264
|
-
this.onAfterRender(this
|
|
264
|
+
this.onAfterRender(this.animationState);
|
|
265
265
|
};
|
|
266
|
-
this
|
|
267
|
-
this
|
|
266
|
+
this.isVisible = true;
|
|
267
|
+
this.clock.start();
|
|
268
268
|
animateFrame();
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
-
|
|
272
|
-
if (this
|
|
273
|
-
cancelAnimationFrame(this
|
|
274
|
-
this
|
|
275
|
-
this
|
|
271
|
+
private stopAnimation() {
|
|
272
|
+
if (this.isVisible) {
|
|
273
|
+
cancelAnimationFrame(this.animationFrameId);
|
|
274
|
+
this.isVisible = false;
|
|
275
|
+
this.clock.stop();
|
|
276
276
|
}
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
-
|
|
279
|
+
private render() {
|
|
280
280
|
this.renderer.render(this.scene, this.camera);
|
|
281
281
|
}
|
|
282
282
|
|
|
@@ -305,21 +305,21 @@ class X {
|
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
dispose() {
|
|
308
|
-
this
|
|
309
|
-
this
|
|
308
|
+
this.onResizeCleanup();
|
|
309
|
+
this.stopAnimation();
|
|
310
310
|
this.clear();
|
|
311
|
-
this
|
|
311
|
+
this._postprocessing?.dispose();
|
|
312
312
|
this.renderer.dispose();
|
|
313
313
|
this.isDisposed = true;
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
|
|
317
|
-
window.removeEventListener('resize', this
|
|
318
|
-
this
|
|
319
|
-
this
|
|
316
|
+
private onResizeCleanup() {
|
|
317
|
+
window.removeEventListener('resize', this.onResize.bind(this));
|
|
318
|
+
this.resizeObserver?.disconnect();
|
|
319
|
+
this.intersectionObserver?.disconnect();
|
|
320
320
|
document.removeEventListener(
|
|
321
321
|
'visibilitychange',
|
|
322
|
-
this
|
|
322
|
+
this.onVisibilityChange.bind(this),
|
|
323
323
|
);
|
|
324
324
|
}
|
|
325
325
|
}
|
|
@@ -357,11 +357,11 @@ class W {
|
|
|
357
357
|
this.velocityData = new Float32Array(3 * config.count).fill(0);
|
|
358
358
|
this.sizeData = new Float32Array(config.count).fill(1);
|
|
359
359
|
this.center = new Vector3();
|
|
360
|
-
this
|
|
360
|
+
this.initializePositions();
|
|
361
361
|
this.setSizes();
|
|
362
362
|
}
|
|
363
363
|
|
|
364
|
-
|
|
364
|
+
private initializePositions() {
|
|
365
365
|
const { config, positionData } = this;
|
|
366
366
|
this.center.toArray(positionData, 0);
|
|
367
367
|
for (let i = 1; i < config.count; i++) {
|
|
@@ -713,11 +713,11 @@ class Z extends InstancedMesh {
|
|
|
713
713
|
super(geometry, material, config.count);
|
|
714
714
|
this.config = config;
|
|
715
715
|
this.physics = new W(config);
|
|
716
|
-
this
|
|
716
|
+
this.setupLights();
|
|
717
717
|
this.setColors(config.colors);
|
|
718
718
|
}
|
|
719
719
|
|
|
720
|
-
|
|
720
|
+
private setupLights() {
|
|
721
721
|
this.ambientLight = new AmbientLight(
|
|
722
722
|
this.config.ambientColor,
|
|
723
723
|
this.config.ambientIntensity,
|