Every joint, pulled apart and named.
Synchronise the arm to the scroll position, in both directions, with one bound value.
const observer = onScroll({
target: sectionEl,
axis: 'y',
sync: true,
enter: 'top top',
leave: 'bottom bottom',
});
One requestAnimationFrame owns the clock. anime.js updates values, three.js draws them — never the other way round.
engine.useDefaultMainLoop = false;
function tick(now) {
engine.update();
for (const cb of callbacks) cb(dt, elapsed);
renderer.render(scene, camera);
}
Everything on this page is one gltf, one RAF loop and one scrub value.