AstraOS's picture
Upload 4 files
8637a12 verified
import WindowManager from './WindowManager.js'
const t = THREE;
let camera, scene, renderer, world;
let near, far;
let pixR = window.devicePixelRatio ? window.devicePixelRatio : 1;
let cubes = [];
let sceneOffsetTarget = {x: 0, y: 0};
let sceneOffset = {x: 0, y: 0};
let today = new Date();
today.setHours(0);
today.setMinutes(0);
today.setSeconds(0);
today.setMilliseconds(0);
today = today.getTime();
let internalTime = getTime();
let windowManager;
let initialized = false;
// get time in seconds since beginning of the day (so that all windows use the same time)
function getTime ()
{
return (new Date().getTime() - today) / 1000.0;
}
if (new URLSearchParams(window.location.search).get("clear"))
{
localStorage.clear();
}
else
{
// this code is essential to circumvent that some browsers preload the content of some pages before you actually hit the url
document.addEventListener("visibilitychange", () =>
{
if (document.visibilityState != 'hidden' && !initialized)
{
init();
}
});
window.onload = () => {
if (document.visibilityState != 'hidden')
{
init();
}
};
function init ()
{
initialized = true;
// add a short timeout because window.offsetX reports wrong values before a short period
setTimeout(() => {
setupScene();
// createParticleSystem();
setupWindowManager();
resize();
updateWindowShape(false);
render();
window.addEventListener('resize', resize);
}, 500)
}
function setupScene ()
{
camera = new t.OrthographicCamera(0, 0, window.innerWidth, window.innerHeight, -10000, 10000);
camera.position.z = 2.5;
near = camera.position.z - .5;
far = camera.position.z + 0.5;
scene = new t.Scene();
scene.background = new t.Color(0.0);
scene.add( camera );
var starGeometry = new THREE.Geometry();
for (let i = 0; i < 5000; i++) {
var star = new THREE.Vector3();
star.x = Math.random() * 5000 - 2000;
star.y = Math.random() * 5000 - 2000;
star.z = Math.random() * 5000 - 2000;
starGeometry.vertices.push(star);
var color = new THREE.Color();
if (Math.random() < 0.5) {
color.setHSL(0.16, 0.5, Math.random() * 0.5 + 0.25);
} else {
color.setHSL(0.0, 0.0, Math.random() * 0.5 + 0.5);
}
starGeometry.colors.push(color);
}
var starMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: THREE.VertexColors
});
var starField = new THREE.Points(starGeometry, starMaterial);
scene.add(starField);
renderer = new t.WebGLRenderer({antialias: true, depthBuffer: true});
renderer.setPixelRatio(pixR);
world = new t.Object3D();
scene.add(world);
renderer.domElement.setAttribute("id", "scene");
document.body.appendChild( renderer.domElement );
// Lights
var light = new THREE.AmbientLight( 0x404040 ); // soft white light
scene.add( light );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.position.set( 0, 128, 128 );
scene.add( directionalLight );
}
function setupWindowManager ()
{
windowManager = new WindowManager();
windowManager.setWinShapeChangeCallback(updateWindowShape);
windowManager.setWinChangeCallback(windowsUpdated);
// here you can add your custom metadata to each windows instance
let metaData = {foo: "bar"};
// this will init the windowmanager and add this window to the centralised pool of windows
windowManager.init(metaData);
// call update windows initially (it will later be called by the win change callback)
windowsUpdated();
}
function windowsUpdated ()
{
updateNumberOfCubes();
}
function updateNumberOfCubes ()
{
let wins = windowManager.getWindows();
cubes.forEach((c) => {
world.remove(c);
})
cubes = [];
for (let i = 0; i < wins.length; i++)
{
let win = wins[i];
let c;
if (i == 0) {
c = new t.Color('hsl(230, 80%, 75%)');
} else if (i == 1) {
c = new t.Color('hsl(350, 60%, 65%)');
} else {
let idBasedHueValue = (win.id % 10) / 10;
let hue;
if(idBasedHueValue < 0.5) {
hue = 240 - (idBasedHueValue * 2 * 60);
} else {
hue = 360 - ((idBasedHueValue - 0.5) * 2 * 60);
}
c = new t.Color(`hsl(${hue}, 50%, 70%)`);
}
let s = 100 + i * 50;
let radius = s / 2;
let sphere = createComplexSphere(radius, c);
sphere.position.x = win.shape.x + (win.shape.w * .5);
sphere.position.y = win.shape.y + (win.shape.h * .5);
world.add(sphere);
cubes.push(sphere);
}
}
function createComplexSphere(radius, color) {
let innerSize = radius * 0.9;
let outerSize = radius;
let innerColor = color;
let outerColor = color;
let complexSphere = new THREE.Group();
let sphereWireframeInner = new THREE.Mesh(
new THREE.IcosahedronGeometry(innerSize, 2),
new THREE.MeshLambertMaterial({
color: innerColor,
wireframe: true,
transparent: true,
shininess: 0
})
);
complexSphere.add(sphereWireframeInner);
let sphereWireframeOuter = new THREE.Mesh(
new THREE.IcosahedronGeometry(outerSize, 3),
new THREE.MeshLambertMaterial({
color: outerColor,
wireframe: true,
transparent: true,
shininess: 0
})
);
complexSphere.add(sphereWireframeOuter);
let sphereGlassInner = new THREE.Mesh(
new THREE.SphereGeometry(innerSize, 32, 32),
new THREE.MeshPhongMaterial({
color: innerColor,
transparent: true,
shininess: 25,
opacity: 0.3
})
);
complexSphere.add(sphereGlassInner);
let sphereGlassOuter = new THREE.Mesh(
new THREE.SphereGeometry(outerSize, 32, 32),
new THREE.MeshPhongMaterial({
color: outerColor,
transparent: true,
shininess: 25,
opacity: 0.3
})
);
complexSphere.add(sphereGlassOuter);
let particlesOuter = createParticles(outerSize, outerColor);
complexSphere.add(particlesOuter);
let particlesInner = createParticles(innerSize, innerColor);
complexSphere.add(particlesInner);
return complexSphere;
}
function createParticles(size, color) {
let geometry = new THREE.Geometry();
for (let i = 0; i < 35000; i++) {
let x = -1 + Math.random() * 2;
let y = -1 + Math.random() * 2;
let z = -1 + Math.random() * 2;
let d = 1 / Math.sqrt(x * x + y * y + z * z);
x *= d * size;
y *= d * size;
z *= d * size;
geometry.vertices.push(new THREE.Vector3(x, y, z));
}
let material = new THREE.PointsMaterial({
size: 0.1,
color: color,
transparent: true
});
return new THREE.Points(geometry, material);
}
function updateWindowShape (easing = true)
{
// storing the actual offset in a proxy that we update against in the render function
sceneOffsetTarget = {x: -window.screenX, y: -window.screenY};
if (!easing) sceneOffset = sceneOffsetTarget;
}
function render ()
{
let t = getTime();
windowManager.update();
// calculate the new position based on the delta between current offset and new offset times a falloff value (to create the nice smoothing effect)
let falloff = .05;
sceneOffset.x = sceneOffset.x + ((sceneOffsetTarget.x - sceneOffset.x) * falloff);
sceneOffset.y = sceneOffset.y + ((sceneOffsetTarget.y - sceneOffset.y) * falloff);
// set the world position to the offset
world.position.x = sceneOffset.x;
world.position.y = sceneOffset.y;
let wins = windowManager.getWindows();
// loop through all our cubes and update their positions based on current window positions
for (let i = 0; i < cubes.length; i++)
{
let complexSphere = cubes[i];
let win = wins[i];
let _t = t;
let posTarget = {x: win.shape.x + (win.shape.w * .5), y: win.shape.y + (win.shape.h * .5)}
complexSphere.position.x = complexSphere.position.x + (posTarget.x - complexSphere.position.x) * falloff;
complexSphere.position.y = complexSphere.position.y + (posTarget.y - complexSphere.position.y) * falloff;
complexSphere.rotation.x = _t * .5;
complexSphere.rotation.y = _t * .3;
updateComplexSphere(complexSphere, t);
};
// updateParticles();
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function updateComplexSphere(complexSphere, elapsedTime) {
let sphereWireframeInner = complexSphere.children[0];
let sphereWireframeOuter = complexSphere.children[1];
let sphereGlassInner = complexSphere.children[2];
let sphereGlassOuter = complexSphere.children[3];
let particlesOuter = complexSphere.children[4];
let particlesInner = complexSphere.children[5];
sphereWireframeInner.rotation.x += 0.002;
sphereWireframeInner.rotation.z += 0.002;
sphereWireframeOuter.rotation.x += 0.001;
sphereWireframeOuter.rotation.z += 0.001;
sphereGlassInner.rotation.y += 0.005;
sphereGlassInner.rotation.z += 0.005;
sphereGlassOuter.rotation.y += 0.01;
sphereGlassOuter.rotation.z += 0.01;
particlesOuter.rotation.y += 0.0005;
particlesInner.rotation.y -= 0.002;
var innerShift = Math.abs(Math.cos(((elapsedTime + 2.5) / 20)));
var outerShift = Math.abs(Math.cos(((elapsedTime + 5) / 10)));
sphereWireframeOuter.material.color.setHSL(0.55, 1, outerShift);
sphereGlassOuter.material.color.setHSL(0.55, 1, outerShift);
particlesOuter.material.color.setHSL(0.55, 1, outerShift);
sphereWireframeInner.material.color.setHSL(0.08, 1, innerShift);
particlesInner.material.color.setHSL(0.08, 1, innerShift);
sphereGlassInner.material.color.setHSL(0.08, 1, innerShift);
sphereWireframeInner.material.opacity = Math.abs(Math.cos((elapsedTime + 0.5) / 0.9) * 0.5);
sphereWireframeOuter.material.opacity = Math.abs(Math.cos(elapsedTime / 0.9) * 0.5);
}
// resize the renderer to fit the window size
function resize ()
{
let width = window.innerWidth;
let height = window.innerHeight
camera = new t.OrthographicCamera(0, width, 0, height, -10000, 10000);
camera.updateProjectionMatrix();
renderer.setSize( width, height );
}
}