AstraOS commited on
Commit
8637a12
·
verified ·
1 Parent(s): 592e7a7

Upload 4 files

Browse files
Files changed (4) hide show
  1. WindowManager.js +151 -0
  2. index.html +20 -19
  3. main.js +375 -0
  4. three.r124.min.js +0 -0
WindowManager.js ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class WindowManager
2
+ {
3
+ #windows;
4
+ #count;
5
+ #id;
6
+ #winData;
7
+ #winShapeChangeCallback;
8
+ #winChangeCallback;
9
+
10
+ constructor ()
11
+ {
12
+ let that = this;
13
+
14
+ // event listener for when localStorage is changed from another window
15
+ addEventListener("storage", (event) =>
16
+ {
17
+ if (event.key == "windows")
18
+ {
19
+ let newWindows = JSON.parse(event.newValue);
20
+ let winChange = that.#didWindowsChange(that.#windows, newWindows);
21
+
22
+ that.#windows = newWindows;
23
+
24
+ if (winChange)
25
+ {
26
+ if (that.#winChangeCallback) that.#winChangeCallback();
27
+ }
28
+ }
29
+ });
30
+
31
+ // event listener for when current window is about to ble closed
32
+ window.addEventListener('beforeunload', function (e)
33
+ {
34
+ let index = that.getWindowIndexFromId(that.#id);
35
+
36
+ //remove this window from the list and update local storage
37
+ that.#windows.splice(index, 1);
38
+ that.updateWindowsLocalStorage();
39
+ });
40
+ }
41
+
42
+ // check if theres any changes to the window list
43
+ #didWindowsChange (pWins, nWins)
44
+ {
45
+ if (pWins.length != nWins.length)
46
+ {
47
+ return true;
48
+ }
49
+ else
50
+ {
51
+ let c = false;
52
+
53
+ for (let i = 0; i < pWins.length; i++)
54
+ {
55
+ if (pWins[i].id != nWins[i].id) c = true;
56
+ }
57
+
58
+ return c;
59
+ }
60
+ }
61
+
62
+ // initiate current window (add metadata for custom data to store with each window instance)
63
+ init (metaData)
64
+ {
65
+ this.#windows = JSON.parse(localStorage.getItem("windows")) || [];
66
+ this.#count= localStorage.getItem("count") || 0;
67
+ this.#count++;
68
+
69
+ this.#id = this.#count;
70
+ let shape = this.getWinShape();
71
+ this.#winData = {id: this.#id, shape: shape, metaData: metaData};
72
+ this.#windows.push(this.#winData);
73
+
74
+ localStorage.setItem("count", this.#count);
75
+ this.updateWindowsLocalStorage();
76
+ }
77
+
78
+ getWinShape ()
79
+ {
80
+ let shape = {x: window.screenLeft, y: window.screenTop, w: window.innerWidth, h: window.innerHeight};
81
+ return shape;
82
+ }
83
+
84
+ getWindowIndexFromId (id)
85
+ {
86
+ let index = -1;
87
+
88
+ for (let i = 0; i < this.#windows.length; i++)
89
+ {
90
+ if (this.#windows[i].id == id) index = i;
91
+ }
92
+
93
+ return index;
94
+ }
95
+
96
+ updateWindowsLocalStorage ()
97
+ {
98
+ localStorage.setItem("windows", JSON.stringify(this.#windows));
99
+ }
100
+
101
+ update ()
102
+ {
103
+ //console.log(step);
104
+ let winShape = this.getWinShape();
105
+
106
+ //console.log(winShape.x, winShape.y);
107
+
108
+ if (winShape.x != this.#winData.shape.x ||
109
+ winShape.y != this.#winData.shape.y ||
110
+ winShape.w != this.#winData.shape.w ||
111
+ winShape.h != this.#winData.shape.h)
112
+ {
113
+
114
+ this.#winData.shape = winShape;
115
+
116
+ let index = this.getWindowIndexFromId(this.#id);
117
+ this.#windows[index].shape = winShape;
118
+
119
+ //console.log(windows);
120
+ if (this.#winShapeChangeCallback) this.#winShapeChangeCallback();
121
+ this.updateWindowsLocalStorage();
122
+ }
123
+ }
124
+
125
+ setWinShapeChangeCallback (callback)
126
+ {
127
+ this.#winShapeChangeCallback = callback;
128
+ }
129
+
130
+ setWinChangeCallback (callback)
131
+ {
132
+ this.#winChangeCallback = callback;
133
+ }
134
+
135
+ getWindows ()
136
+ {
137
+ return this.#windows;
138
+ }
139
+
140
+ getThisWindowData ()
141
+ {
142
+ return this.#winData;
143
+ }
144
+
145
+ getThisWindowID ()
146
+ {
147
+ return this.#id;
148
+ }
149
+ }
150
+
151
+ export default WindowManager;
index.html CHANGED
@@ -1,19 +1,20 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>3d example using three.js and multiple windows</title>
5
+ <script type="text/javascript" src="three.r124.min.js"></script>
6
+ <style type="text/css">
7
+
8
+ *
9
+ {
10
+ margin: 0;
11
+ padding: 0;
12
+ }
13
+
14
+ </style>
15
+ </head>
16
+ <body>
17
+
18
+ <script type="module" src="main.js"></script>
19
+ </body>
20
+ </html>
main.js ADDED
@@ -0,0 +1,375 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import WindowManager from './WindowManager.js'
2
+
3
+
4
+ const t = THREE;
5
+ let camera, scene, renderer, world;
6
+ let near, far;
7
+ let pixR = window.devicePixelRatio ? window.devicePixelRatio : 1;
8
+ let cubes = [];
9
+ let sceneOffsetTarget = {x: 0, y: 0};
10
+ let sceneOffset = {x: 0, y: 0};
11
+
12
+ let today = new Date();
13
+ today.setHours(0);
14
+ today.setMinutes(0);
15
+ today.setSeconds(0);
16
+ today.setMilliseconds(0);
17
+ today = today.getTime();
18
+
19
+ let internalTime = getTime();
20
+ let windowManager;
21
+ let initialized = false;
22
+
23
+ // get time in seconds since beginning of the day (so that all windows use the same time)
24
+ function getTime ()
25
+ {
26
+ return (new Date().getTime() - today) / 1000.0;
27
+ }
28
+
29
+
30
+ if (new URLSearchParams(window.location.search).get("clear"))
31
+ {
32
+ localStorage.clear();
33
+ }
34
+ else
35
+ {
36
+ // this code is essential to circumvent that some browsers preload the content of some pages before you actually hit the url
37
+ document.addEventListener("visibilitychange", () =>
38
+ {
39
+ if (document.visibilityState != 'hidden' && !initialized)
40
+ {
41
+ init();
42
+ }
43
+ });
44
+
45
+ window.onload = () => {
46
+ if (document.visibilityState != 'hidden')
47
+ {
48
+ init();
49
+ }
50
+ };
51
+
52
+
53
+ function init ()
54
+ {
55
+ initialized = true;
56
+
57
+ // add a short timeout because window.offsetX reports wrong values before a short period
58
+ setTimeout(() => {
59
+ setupScene();
60
+ // createParticleSystem();
61
+ setupWindowManager();
62
+ resize();
63
+ updateWindowShape(false);
64
+ render();
65
+ window.addEventListener('resize', resize);
66
+ }, 500)
67
+ }
68
+
69
+
70
+ function setupScene ()
71
+ {
72
+ camera = new t.OrthographicCamera(0, 0, window.innerWidth, window.innerHeight, -10000, 10000);
73
+
74
+ camera.position.z = 2.5;
75
+ near = camera.position.z - .5;
76
+ far = camera.position.z + 0.5;
77
+
78
+ scene = new t.Scene();
79
+ scene.background = new t.Color(0.0);
80
+ scene.add( camera );
81
+
82
+ var starGeometry = new THREE.Geometry();
83
+ for (let i = 0; i < 5000; i++) {
84
+ var star = new THREE.Vector3();
85
+ star.x = Math.random() * 5000 - 2000;
86
+ star.y = Math.random() * 5000 - 2000;
87
+ star.z = Math.random() * 5000 - 2000;
88
+ starGeometry.vertices.push(star);
89
+ var color = new THREE.Color();
90
+ if (Math.random() < 0.5) {
91
+ color.setHSL(0.16, 0.5, Math.random() * 0.5 + 0.25);
92
+ } else {
93
+ color.setHSL(0.0, 0.0, Math.random() * 0.5 + 0.5);
94
+ }
95
+ starGeometry.colors.push(color);
96
+ }
97
+
98
+ var starMaterial = new THREE.PointsMaterial({
99
+ size: 2,
100
+ vertexColors: THREE.VertexColors
101
+ });
102
+
103
+ var starField = new THREE.Points(starGeometry, starMaterial);
104
+ scene.add(starField);
105
+
106
+ renderer = new t.WebGLRenderer({antialias: true, depthBuffer: true});
107
+ renderer.setPixelRatio(pixR);
108
+
109
+ world = new t.Object3D();
110
+ scene.add(world);
111
+
112
+ renderer.domElement.setAttribute("id", "scene");
113
+ document.body.appendChild( renderer.domElement );
114
+
115
+ // Lights
116
+ var light = new THREE.AmbientLight( 0x404040 ); // soft white light
117
+ scene.add( light );
118
+
119
+ var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
120
+ directionalLight.position.set( 0, 128, 128 );
121
+ scene.add( directionalLight );
122
+
123
+ }
124
+
125
+
126
+ function setupWindowManager ()
127
+ {
128
+ windowManager = new WindowManager();
129
+ windowManager.setWinShapeChangeCallback(updateWindowShape);
130
+ windowManager.setWinChangeCallback(windowsUpdated);
131
+
132
+ // here you can add your custom metadata to each windows instance
133
+ let metaData = {foo: "bar"};
134
+
135
+ // this will init the windowmanager and add this window to the centralised pool of windows
136
+ windowManager.init(metaData);
137
+
138
+ // call update windows initially (it will later be called by the win change callback)
139
+ windowsUpdated();
140
+ }
141
+
142
+
143
+ function windowsUpdated ()
144
+ {
145
+ updateNumberOfCubes();
146
+ }
147
+
148
+
149
+ function updateNumberOfCubes ()
150
+ {
151
+ let wins = windowManager.getWindows();
152
+
153
+ cubes.forEach((c) => {
154
+ world.remove(c);
155
+ })
156
+
157
+ cubes = [];
158
+
159
+ for (let i = 0; i < wins.length; i++)
160
+ {
161
+ let win = wins[i];
162
+
163
+ let c;
164
+ if (i == 0) {
165
+ c = new t.Color('hsl(230, 80%, 75%)');
166
+ } else if (i == 1) {
167
+ c = new t.Color('hsl(350, 60%, 65%)');
168
+ } else {
169
+ let idBasedHueValue = (win.id % 10) / 10;
170
+ let hue;
171
+ if(idBasedHueValue < 0.5) {
172
+ hue = 240 - (idBasedHueValue * 2 * 60);
173
+ } else {
174
+ hue = 360 - ((idBasedHueValue - 0.5) * 2 * 60);
175
+ }
176
+ c = new t.Color(`hsl(${hue}, 50%, 70%)`);
177
+ }
178
+
179
+ let s = 100 + i * 50;
180
+ let radius = s / 2;
181
+
182
+ let sphere = createComplexSphere(radius, c);
183
+ sphere.position.x = win.shape.x + (win.shape.w * .5);
184
+ sphere.position.y = win.shape.y + (win.shape.h * .5);
185
+
186
+ world.add(sphere);
187
+ cubes.push(sphere);
188
+
189
+ }
190
+ }
191
+
192
+
193
+ function createComplexSphere(radius, color) {
194
+ let innerSize = radius * 0.9;
195
+ let outerSize = radius;
196
+ let innerColor = color;
197
+ let outerColor = color;
198
+
199
+ let complexSphere = new THREE.Group();
200
+
201
+ let sphereWireframeInner = new THREE.Mesh(
202
+ new THREE.IcosahedronGeometry(innerSize, 2),
203
+ new THREE.MeshLambertMaterial({
204
+ color: innerColor,
205
+ wireframe: true,
206
+ transparent: true,
207
+ shininess: 0
208
+ })
209
+ );
210
+ complexSphere.add(sphereWireframeInner);
211
+
212
+ let sphereWireframeOuter = new THREE.Mesh(
213
+ new THREE.IcosahedronGeometry(outerSize, 3),
214
+ new THREE.MeshLambertMaterial({
215
+ color: outerColor,
216
+ wireframe: true,
217
+ transparent: true,
218
+ shininess: 0
219
+ })
220
+ );
221
+ complexSphere.add(sphereWireframeOuter);
222
+
223
+
224
+ let sphereGlassInner = new THREE.Mesh(
225
+ new THREE.SphereGeometry(innerSize, 32, 32),
226
+ new THREE.MeshPhongMaterial({
227
+ color: innerColor,
228
+ transparent: true,
229
+ shininess: 25,
230
+ opacity: 0.3
231
+ })
232
+ );
233
+ complexSphere.add(sphereGlassInner);
234
+
235
+ let sphereGlassOuter = new THREE.Mesh(
236
+ new THREE.SphereGeometry(outerSize, 32, 32),
237
+ new THREE.MeshPhongMaterial({
238
+ color: outerColor,
239
+ transparent: true,
240
+ shininess: 25,
241
+ opacity: 0.3
242
+ })
243
+ );
244
+ complexSphere.add(sphereGlassOuter);
245
+
246
+ let particlesOuter = createParticles(outerSize, outerColor);
247
+ complexSphere.add(particlesOuter);
248
+
249
+ let particlesInner = createParticles(innerSize, innerColor);
250
+ complexSphere.add(particlesInner);
251
+
252
+ return complexSphere;
253
+ }
254
+
255
+ function createParticles(size, color) {
256
+ let geometry = new THREE.Geometry();
257
+ for (let i = 0; i < 35000; i++) {
258
+ let x = -1 + Math.random() * 2;
259
+ let y = -1 + Math.random() * 2;
260
+ let z = -1 + Math.random() * 2;
261
+ let d = 1 / Math.sqrt(x * x + y * y + z * z);
262
+ x *= d * size;
263
+ y *= d * size;
264
+ z *= d * size;
265
+ geometry.vertices.push(new THREE.Vector3(x, y, z));
266
+ }
267
+ let material = new THREE.PointsMaterial({
268
+ size: 0.1,
269
+ color: color,
270
+ transparent: true
271
+ });
272
+ return new THREE.Points(geometry, material);
273
+ }
274
+
275
+
276
+ function updateWindowShape (easing = true)
277
+ {
278
+ // storing the actual offset in a proxy that we update against in the render function
279
+ sceneOffsetTarget = {x: -window.screenX, y: -window.screenY};
280
+ if (!easing) sceneOffset = sceneOffsetTarget;
281
+ }
282
+
283
+
284
+ function render ()
285
+ {
286
+ let t = getTime();
287
+
288
+ windowManager.update();
289
+
290
+ // calculate the new position based on the delta between current offset and new offset times a falloff value (to create the nice smoothing effect)
291
+ let falloff = .05;
292
+ sceneOffset.x = sceneOffset.x + ((sceneOffsetTarget.x - sceneOffset.x) * falloff);
293
+ sceneOffset.y = sceneOffset.y + ((sceneOffsetTarget.y - sceneOffset.y) * falloff);
294
+
295
+ // set the world position to the offset
296
+ world.position.x = sceneOffset.x;
297
+ world.position.y = sceneOffset.y;
298
+
299
+ let wins = windowManager.getWindows();
300
+
301
+ // loop through all our cubes and update their positions based on current window positions
302
+ for (let i = 0; i < cubes.length; i++)
303
+ {
304
+ let complexSphere = cubes[i];
305
+ let win = wins[i];
306
+ let _t = t;
307
+
308
+ let posTarget = {x: win.shape.x + (win.shape.w * .5), y: win.shape.y + (win.shape.h * .5)}
309
+
310
+ complexSphere.position.x = complexSphere.position.x + (posTarget.x - complexSphere.position.x) * falloff;
311
+ complexSphere.position.y = complexSphere.position.y + (posTarget.y - complexSphere.position.y) * falloff;
312
+
313
+
314
+ complexSphere.rotation.x = _t * .5;
315
+ complexSphere.rotation.y = _t * .3;
316
+ updateComplexSphere(complexSphere, t);
317
+ };
318
+
319
+ // updateParticles();
320
+ renderer.render(scene, camera);
321
+ requestAnimationFrame(render);
322
+ }
323
+
324
+
325
+ function updateComplexSphere(complexSphere, elapsedTime) {
326
+ let sphereWireframeInner = complexSphere.children[0];
327
+ let sphereWireframeOuter = complexSphere.children[1];
328
+ let sphereGlassInner = complexSphere.children[2];
329
+ let sphereGlassOuter = complexSphere.children[3];
330
+ let particlesOuter = complexSphere.children[4];
331
+ let particlesInner = complexSphere.children[5];
332
+
333
+ sphereWireframeInner.rotation.x += 0.002;
334
+ sphereWireframeInner.rotation.z += 0.002;
335
+
336
+ sphereWireframeOuter.rotation.x += 0.001;
337
+ sphereWireframeOuter.rotation.z += 0.001;
338
+
339
+ sphereGlassInner.rotation.y += 0.005;
340
+ sphereGlassInner.rotation.z += 0.005;
341
+
342
+ sphereGlassOuter.rotation.y += 0.01;
343
+ sphereGlassOuter.rotation.z += 0.01;
344
+
345
+ particlesOuter.rotation.y += 0.0005;
346
+ particlesInner.rotation.y -= 0.002;
347
+
348
+ var innerShift = Math.abs(Math.cos(((elapsedTime + 2.5) / 20)));
349
+ var outerShift = Math.abs(Math.cos(((elapsedTime + 5) / 10)));
350
+
351
+ sphereWireframeOuter.material.color.setHSL(0.55, 1, outerShift);
352
+ sphereGlassOuter.material.color.setHSL(0.55, 1, outerShift);
353
+ particlesOuter.material.color.setHSL(0.55, 1, outerShift);
354
+
355
+ sphereWireframeInner.material.color.setHSL(0.08, 1, innerShift);
356
+ particlesInner.material.color.setHSL(0.08, 1, innerShift);
357
+ sphereGlassInner.material.color.setHSL(0.08, 1, innerShift);
358
+
359
+ sphereWireframeInner.material.opacity = Math.abs(Math.cos((elapsedTime + 0.5) / 0.9) * 0.5);
360
+ sphereWireframeOuter.material.opacity = Math.abs(Math.cos(elapsedTime / 0.9) * 0.5);
361
+
362
+ }
363
+
364
+
365
+ // resize the renderer to fit the window size
366
+ function resize ()
367
+ {
368
+ let width = window.innerWidth;
369
+ let height = window.innerHeight
370
+
371
+ camera = new t.OrthographicCamera(0, width, 0, height, -10000, 10000);
372
+ camera.updateProjectionMatrix();
373
+ renderer.setSize( width, height );
374
+ }
375
+ }
three.r124.min.js ADDED
The diff for this file is too large to render. See raw diff