Skip to content
Creative Marketing AI

Motion Showcase

Ambient & Texture

The garnish layer — small alive details that sit on top of a scene. Scroll fast, scroll slow, then stop and move your cursor around the button and the cards near the bottom.

01 · Velocity skew

The row shears with your scroll speed and eases back upright when you stop — flick the wheel hard to feel it.

ScrollTrigger.create({ onUpdate: s => skewTo(clamp(s.getVelocity() / -300)) })
02 · Marquee drift

A doubled row loops forever at walking pace; scrolling pours energy into it — speed and direction follow your scroll, then settle back to idle.

gsap.to(track, { xPercent: -50, repeat: -1, ease: 'none' }) // timeScale follows velocity
03 · Canvas particlesLodge courtyard at night, still air

120 snowflakes from a single 32px sprite — depth drives size, fall speed and alpha, a sine wave drives the twinkle. The loop only runs while this scene is on screen.

ScrollTrigger.create({ pin: true, onToggle: s => s.isActive ? startRaf() : stopRaf() })
04 · Grain overlayWorkshop wide shot, silhouette

An SVG feTurbulence tile at low opacity, its position jumped in steps — cheap 35mm film grain with no video file and no canvas.

feTurbulence tile → gsap.to(grain, { backgroundPosition: '240px 160px', ease: 'steps(7)', repeat: -1 })
05 · Magnetic buttonReserve a table

Within 120px the button leans toward your cursor; leave and it snaps home on an elastic. Desktop pointers only — touch never sees it.

const xTo = gsap.quickTo(btn, 'x', { duration: 0.9, ease: 'elastic.out(1, 0.35)' })
06 · Hover parallax cards
Banquet table detailThe table
Black marble product stageThe stage
Craftsman hands close-upThe hands

Each card tilts up to six degrees toward the cursor on a 700px perspective — enough to feel dimensional, never enough to feel like a gimmick.

quickTo(card, 'rotationY')((cursorX - 0.5) * 12) // clamped to ±6°

Keep going

Next up: a real film scrubbed frame-by-frame by your scroll position.

← All effectsNext: Film Scrub →