Working on a larger -personal- project involving a similar animation. Still tooling with it.
A Pen by Sean Dempsey on CodePen.
/* 'To actually be able to display anything with Three.js, we need three things: | |
A scene, a camera, and a renderer so we can render the scene with the camera.' | |
- http://threejs.org/docs/#Manual/Introduction/Creating_a_scene */ | |
var scene, camera, renderer; | |
/* I guess we need this stuff too */ | |
var container, HEIGHT, | |
WIDTH, fieldOfView, aspectRatio, | |
nearPlane, farPlane, stats, | |
geometry, particleCount, | |
i, h, color, size, materials = [], | |
mouseX = 0, mouseY = 0, windowHalfX, windowHalfY; | |
init(); | |
animate(); | |
function init() { | |
HEIGHT = window.innerHeight; | |
WIDTH = window.innerWidth; | |
windowHalfX = WIDTH / 2; | |
windowHalfY = HEIGHT / 2; | |
fieldOfView = 75; | |
aspectRatio = WIDTH / HEIGHT; | |
nearPlane = 1; | |
farPlane = 3000; | |
/* fieldOfView — Camera frustum vertical field of view. | |
aspectRatio — Camera frustum aspect ratio. | |
nearPlane — Camera frustum near plane. | |
farPlane — Camera frustum far plane. | |
- http://threejs.org/docs/#Reference/Cameras/PerspectiveCamera | |
In geometry, a frustum (plural: frusta or frustums) | |
is the portion of a solid (normally a cone or pyramid) | |
that lies between two parallel planes cutting it. - wikipedia. */ | |
cameraZ = farPlane / 3; /* So, 1000? Yes! move on! */ | |
fogHex = 0x000000; /* As black as your heart. */ | |
fogDensity = 0.0007; /* So not terribly dense? */ | |
camera = new THREE.PerspectiveCamera(fieldOfView, aspectRatio, nearPlane, farPlane); | |
camera.position.z = cameraZ; | |
scene = new THREE.Scene(); | |
scene.fog = new THREE.FogExp2(fogHex, fogDensity); | |
container = document.createElement('div'); | |
document.body.appendChild(container); | |
document.body.style.overflow = 'hidden'; | |
geometry = new THREE.Geometry(); /* NO ONE SAID ANYTHING ABOUT MATH! UGH! */ | |
particleCount = 20000; /* Leagues under the sea */ | |
/* Hope you took your motion sickness pills; | |
We're about to get loopy. */ | |
for (i = 0; i < particleCount; i++) { | |
var vertex = new THREE.Vector3(); | |
vertex.x = Math.random() * 2000 - 1000; | |
vertex.y = Math.random() * 2000 - 1000; | |
vertex.z = Math.random() * 2000 - 1000; | |
geometry.vertices.push(vertex); | |
} | |
/* We can't stop here, this is bat country! */ | |
parameters = [[[1, 1, 0.5], 5], [[0.95, 1, 0.5], 4], [[0.90, 1, 0.5], 3], [[0.85, 1, 0.5], 2], [[0.80, 1, 0.5], 1]]; | |
parameterCount = parameters.length; | |
/* I told you to take those motion sickness pills. | |
Clean that vommit up, we're going again! */ | |
for (i = 0; i < parameterCount; i++) { | |
color = parameters[i][0]; | |
size = parameters[i][1]; | |
materials[i] = new THREE.PointCloudMaterial({size:size}); | |
particles = new THREE.PointCloud(geometry, materials[i]); | |
particles.rotation.x = Math.random() * 6; | |
particles.rotation.y = Math.random() * 6; | |
particles.rotation.z = Math.random() * 6; | |
scene.add(particles); | |
} | |
/* If my calculations are correct, when this baby hits 88 miles per hour... | |
you're gonna see some serious shit. */ | |
renderer = new THREE.WebGLRenderer(); /* Rendererererers particles. */ | |
renderer.setPixelRatio(window.devicePixelRatio); /* Probably 1; unless you're fancy. */ | |
renderer.setSize(WIDTH, HEIGHT); /* Full screen baby Wooooo! */ | |
container.appendChild(renderer.domElement); /* Let's add all this crazy junk to the page. */ | |
/* I don't know about you, but I like to know how bad my | |
code is wrecking the performance of a user's machine. | |
Let's see some damn stats! */ | |
stats = new Stats(); | |
stats.domElement.style.position = 'absolute'; | |
stats.domElement.style.top = '0px'; | |
stats.domElement.style.right = '0px'; | |
container.appendChild( stats.domElement ); | |
/* Event Listeners */ | |
window.addEventListener('resize', onWindowResize, false); | |
document.addEventListener('mousemove', onDocumentMouseMove, false); | |
document.addEventListener('touchstart', onDocumentTouchStart, false); | |
document.addEventListener('touchmove', onDocumentTouchMove, false); | |
} | |
function animate() { | |
requestAnimationFrame(animate); | |
render(); | |
stats.update(); | |
} | |
function render() { | |
var time = Date.now() * 0.00005; | |
camera.position.x += (mouseX - camera.position.x) * 0.05; | |
camera.position.y += (- mouseY - camera.position.y) * 0.05; | |
camera.lookAt(scene.position); | |
for (i = 0; i < scene.children.length; i ++) { | |
var object = scene.children[i]; | |
if (object instanceof THREE.PointCloud) { | |
object.rotation.y = time * (i < 4 ? i + 1 : - (i + 1)); | |
} | |
} | |
for (i = 0; i < materials.length; i ++) { | |
color = parameters[i][0]; | |
h = (360 * (color[0] + time) % 360) / 360; | |
materials[i].color.setHSL(h, color[1], color[2]); | |
} | |
renderer.render(scene, camera); | |
} | |
function onDocumentMouseMove(e) { | |
mouseX = e.clientX - windowHalfX; | |
mouseY = e.clientY - windowHalfY; | |
} | |
/* Mobile users? I got your back homey */ | |
function onDocumentTouchStart(e) { | |
if (e.touches.length === 1) { | |
e.preventDefault(); | |
mouseX = e.touches[0].pageX - windowHalfX; | |
mouseY = e.touches[0].pageY - windowHalfY; | |
} | |
} | |
function onDocumentTouchMove(e) { | |
if (e.touches.length === 1) { | |
e.preventDefault(); | |
mouseX = e.touches[ 0 ].pageX - windowHalfX; | |
mouseY = e.touches[ 0 ].pageY - windowHalfY; | |
} | |
} | |
function onWindowResize() { | |
windowHalfX = window.innerWidth / 2; | |
windowHalfY = window.innerHeight / 2; | |
camera.aspect = window.innerWidth / window.innerHeight; | |
camera.updateProjectionMatrix(); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
} |
Working on a larger -personal- project involving a similar animation. Still tooling with it.
A Pen by Sean Dempsey on CodePen.