Scroll 3D Object

Lesson 12

A CSS 3D cube (transform-style: preserve-3d, six .face divs) rotates 360° as the page scrolls. A GSAP timeline with scrollTrigger: { pin: true, scrub: 1, end: '+=3000' } drives rotateY: 360. A secondary rotateX tween adds a lean-back-and-return arc for visual interest.

Source Code script.js
gsap.registerPlugin(ScrollTrigger);

const FACES = [
  { name: 'front',  min: 0,   max: 45  },
  { name: 'right',  min: 45,  max: 135 },
  { name: 'back',   min: 135, max: 225 },
  { name: 'left',   min: 225, max: 315 },
  { name: 'front',  min: 315, max: 360 },
];

const label = document.querySelector('.face-label');

function getFaceName(deg) {
  const d = ((deg % 360) + 360) % 360;
  for (const f of FACES) {
    if (d >= f.min && d < f.max) return f.name;
  }
  return 'front';
}

const tl = gsap.timeline({
  scrollTrigger: {
    trigger: '.stage',
    start: 'top top',
    end: '+=3000',
    pin: true,
    scrub: 1,
    invalidateOnRefresh: true,
    onUpdate(self) {
      const deg = self.progress * 360;
      label.textContent = getFaceName(deg);
    },
  },
});

tl.to('.cube', { rotateY: 360, ease: 'none' }, 0)
  .to('.cube', { rotateX: -15, ease: 'none' }, 0)
  .to('.cube', { rotateX: 0, ease: 'none' }, 0.5);