Public
Edited
Sep 29, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
renderer.domElement
Insert cell
// Continuously updates
{
while (true) {
renderer.render(scene, camera);
yield null;
}
}
Insert cell
{
// Bring in the animation control buttons
const buttonParticles1 = document.querySelector('#particles-1')
const buttonParticles2 = document.querySelector('#particles-2')
// Add event listeners such that the first button plays the particle animation forwards and the second one backwards
buttonParticles1.addEventListener('click', () => {
gsapAnimateFrom1to2()
})
buttonParticles2.addEventListener('click', () => {
gsapAnimateFrom2to1()
})
}
Insert cell
Insert cell
gsapAnimateFrom1to2 = () => {
gsap.to(particles.geometry.attributes.position.array, {
endArray: particles2.geometry.attributes.position.array,
duration: 3,
ease: 'power2',
// Make sure to tell it to update if not using the tick function
onUpdate: () => {
particles.geometry.attributes.position.needsUpdate = true;
camera.lookAt(particles.position);
renderer.render(scene, camera);
},
})
}
Insert cell
gsapAnimateFrom2to1 = () => {
gsap.to(particles.geometry.attributes.position.array, {
endArray: particles1.geometry.attributes.position.array,
duration: 3,
ease: 'power2',
// Make sure to tell it to update if not using the tick function
onUpdate: () => {
particles.geometry.attributes.position.needsUpdate = true;
// controls.update() -- only works while it's updating
camera.lookAt(particles.position);
renderer.render(scene, camera);
},
})
}
Insert cell
Insert cell
particles = new THREE.Points(geometry, material) // Starting particles; geometry is a copy of geometry1 for particles1
Insert cell
particles1 = new THREE.Points(geometry1, material)
Insert cell
particles2 = new THREE.Points(geometry2, material)
Insert cell
Insert cell
geometry = new THREE.BufferGeometry()
Insert cell
geometry1 = new THREE.BufferGeometry()
Insert cell
positions1 = {
const positions1 = new Float32Array(MAX_POINTS * 3)
for (let i = 0; i < MAX_POINTS; i++) {
const i3 = i * 3
positions1[i3 + 0] = (Math.random() - 0.5) * 10
positions1[i3 + 1] = (Math.random() - 0.5) * 10
positions1[i3 + 2] = (Math.random() - 0.5) * 10
}
return positions1
}
Insert cell
geometry1.setAttribute('position', new THREE.BufferAttribute(positions1, 3))
Insert cell
geometry.setAttribute('position', new THREE.BufferAttribute(positions1.slice(), 3))
Insert cell
geometry2 = new THREE.BufferGeometry()
Insert cell
positions2 = {
const positions2 = new Float32Array(MAX_POINTS * 3)
for (let i = 0; i < MAX_POINTS; i++) {
const i3 = i * 3
positions2[i3 + 0] = (Math.random() - 0.5) * 30
positions2[i3 + 1] = (Math.random() - 0.5) * 30
positions2[i3 + 2] = (Math.random() - 0.5) * 30
}
return positions2
}
Insert cell
geometry2.setAttribute('position', new THREE.BufferAttribute(positions2, 3))
Insert cell
Insert cell
material = new THREE.PointsMaterial({
color: '#B5255A',
size: textureType === 'none' || !textureType ? 0.15 : 0.75,
sizeAttenuation: true,
transparent: true,
depthWrite: false,
alphaMap: textureType === 'none' || !textureType ? false : particleTexture,
blending: textureType === 'none' || !textureType ? false : THREE.AdditiveBlending,
})
Insert cell
Insert cell
particleTexture = textureLoader.load(`https://raw.githubusercontent.com/deaxmachina/example_threejs-demos/main/public/textures/particles/${textureOptions[textureType]}`)
Insert cell
Insert cell
Insert cell
scene = {
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x001b42); // 0x001b42
scene.add(particles);
return scene;
}
Insert cell
Insert cell
camera = {
const fov = 45;
const aspect = width / height;
const near = 1;
const far = 100;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(10, 10, 25)
camera.lookAt(new THREE.Vector3(0, 0, 0));
return camera;
}
Insert cell
Insert cell
renderer = {
const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(width, height);
renderer.setPixelRatio(devicePixelRatio);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener("change", () => renderer.render(scene, camera));
invalidation.then(() => (controls.dispose(), renderer.dispose()));
return renderer;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more