var urlParamsForBackground = new URLSearchParams(window.location.search); if (urlParamsForBackground.get('forward') == 'langstudy.tech-homepage.html') { throw new Error("Halting 3d background. A integration specified the current page should not have a 3d background."); } color = 0xffffff pointcolor = 0x000000 if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { color = 0x000000 pointcolor = 0xffffff var style = document.createElement('style'); style.innerHTML = ` body { --primary-color: #000000 !important; --secondary-color: #ffffff !important; } `; document.head.appendChild(style); } var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 ); var renderer = new THREE.WebGLRenderer(antiAlias = true); renderer.setSize( window.innerWidth, window.innerHeight); rendererElement = renderer.domElement rendererElement.style.position = 'absolute' rendererElement.style.top = 0 rendererElement.style.left = 0 rendererElement.style.zIndex = -5 document.body.appendChild( rendererElement ); window.addEventListener("mousemove", function(event) { let mouseY = event.clientY let windowHeight = window.innerHeight targetCameraPosY = -((mouseY - windowHeight / 2) / 500) + 5 }); function lerp(a, b, t) { return a + (b - a) * t } // loop over a 2D grid of points spheres = [] sphereHeightOffset = [] for ( var x = -40; x <= 40; x += 1 ) { for ( var z = -20; z <= 5; z += 1) { var geometry = new THREE.SphereGeometry( 0.05, 32, 32 ); var material = new THREE.MeshBasicMaterial( {color: pointcolor} ) var sphere = new THREE.Mesh( geometry, material ); sphere.position.x = x sphere.position.z = z var height = Math.pow(z, 2) / 70 // height = 0 sphere.position.y = height sphereHeightOffset.push(height) spheres.push(sphere) scene.add( sphere ); } } // set the skybox to white scene.background = new THREE.Color( color ); camera.position.z = 10; camera.position.y = 5; time = 0 rate = 2 noise.seed(Math.random()) var animate = function () { requestAnimationFrame( animate ); renderer.render( scene, camera ); time_since_last_resize += 1; for (var i = 0; i < spheres.length; i++) { var sphere = spheres[i] var x = sphere.position.x var z = sphere.position.z var height = noise.simplex2(x/10 + (time / rate), z/10 + (time / rate)) * 0.5 sphere.position.y = height + sphereHeightOffset[i] var color = new THREE.Color( 0xffffff ); color.setHSL( 0, 0, height + 0.5 ); sphere.material.color = color sphere.scale.x = 1 + height sphere.scale.y = 1 + height sphere.scale.z = 1 + height } camera.position.y = lerp(camera.position.y, targetCameraPosY, 0.1) time += 0.01 if (time_since_last_resize > 5) { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); window_needs_resize = false; } }; var window_needs_resize = false; var time_since_last_resize = 0; window.addEventListener( 'resize', onWindowResize, false ); function onWindowResize(){ time_since_last_resize = 0; window_needs_resize = true; } animate();