Spaces:
Running
Running
Upload 4 files
Browse files- WindowManager.js +151 -0
- index.html +20 -19
- main.js +375 -0
- 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 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
</
|
|
|
|
|
|
| 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
|
|
|