Back to Blog
Engineering8 min read

Building a Cinematic Demo Viewer: Spring Physics, Spotlights, and Virtual Cursors

A deep-dive into building a premium interactive demo viewer with spring-based cameras, GPU-composited spotlights, virtual cursors, and physics-driven animations.

R

Riveo Engineering

8 min read

Why "Good Enough" Isn't

Most interactive demo tools render their viewers as glorified slideshows: a static image, a highlighted rectangle, a tooltip, a "Next" button. It works, but it feels like a PowerPoint deck wearing a trench coat. The moment a prospect senses that the "demo" is just a slideshow, the illusion of using a real product collapses.

Building a cinematic demo viewer means making every transition, every highlight, and every cursor movement feel alive — as if the viewer is watching (and controlling) a real product session. This post walks through the engineering decisions behind that experience.

The Spring-Driven Camera

When a demo step focuses on a specific region of the screen — say, a button in the top-right corner — the viewer needs to pan and zoom to that region. The naive approach is a CSS transition: transform 0.3s ease-in-out. It's smooth, but it feels robotic. Every movement has the same duration, the same easing, the same mechanical quality.

Spring physics solve this. Instead of defining a duration and easing curve, you define physical properties: stiffness, damping, and mass. The animation emerges from simulating a damped harmonic oscillator. Short movements resolve quickly; large pans take longer and carry more momentum. The result feels organic because it is organic — it follows the same equations that govern real physical motion.

Implementing Springs with requestAnimationFrame

A spring simulation runs on every frame. The core loop looks like this: on each requestAnimationFrame tick, compute the spring force pulling the current value toward the target, apply damping proportional to velocity, integrate to get the new position and velocity, and update the DOM. The simulation stops when both displacement and velocity fall below a threshold — the spring has "settled."

Using requestAnimationFrame instead of CSS transitions gives you two critical capabilities: interruptibility (you can retarget mid-flight if the user clicks ahead) and composition (you can drive multiple properties — pan X, pan Y, zoom — from independent springs that resolve at different rates, creating natural parallax).

GPU-Composited Spotlight Masks

The spotlight effect — dimming everything except the region of interest — is a signature element of a polished demo viewer. The naive implementation layers a semi-transparent overlay with a CSS clip-path cutout. This works at small scale, but clip-path animations trigger layout recalculations and can jank on mid-range hardware.

A more performant approach uses a radial gradient mask on a full-viewport overlay, animated via transform and opacity — both of which are compositor-only properties that bypass the main thread entirely. The mask position tracks the hotspot region, driven by the same spring system as the camera. Because the mask and the camera share spring parameters, the spotlight follows the viewport pan with perfect synchronization.

Rounded Rectangle Cutouts

Real UI elements have border radii. A circular spotlight looks unnatural over a rounded button. To produce a rounded-rectangle cutout, you can use an SVG <mask> element with an animated <rect rx="..." ry="...">. SVG masks composite on the GPU when applied to elements that are already on their own compositor layer (promoted via will-change: transform or translateZ(0)). The result is a silky cutout that matches the shape of the target element.

Virtual Cursor Choreography

A virtual cursor — an animated pointer that moves to each hotspot — bridges the gap between "here's a highlighted region" and "here's what clicking looks like." It guides the viewer's attention and makes the demo feel like a live session.

The cursor's movement path is critical. A straight line from point A to point B looks mechanical. Real mouse movements follow slight curves — humans don't move in perfectly straight lines. Adding a subtle Bézier curve between the origin and destination, with a control point offset perpendicular to the direct path, produces a naturalistic arc.

Timing matters too. The cursor should accelerate out of rest, cruise during the middle segment, and decelerate as it approaches the target — mimicking Fitts's Law dynamics. Springs handle this naturally: a spring-driven cursor accelerates under the spring force, reaches peak velocity mid-flight, and decelerates as it nears the target. Add a small "settle" oscillation at the end, and the cursor feels like a real hand guiding the viewer.

Click Ripple Effects

When the virtual cursor "clicks," a ripple animation radiates from the click point. This is a simple expanding circle with fading opacity, but the timing is important: the ripple should begin slightly before the step transition starts, giving the viewer a causal cue — "I clicked here, and that happened." A 100–150ms lead time before the scene change creates a tight cause-and-effect perception.

Tooltip Sequencing and Entrance Animations

Tooltips in a cinematic viewer don't just appear — they arrive. A well-sequenced tooltip entrance follows a specific order:

  • The camera pans to the target region (spring animation, ~300–500ms).
  • The spotlight mask settles on the hotspot (~200ms after the camera begins).
  • The virtual cursor glides to the hotspot (~250ms after the spotlight settles).
  • The tooltip fades and slides in from below (~150ms after the cursor arrives).

This staggered choreography creates a sense of intentional pacing. Each element leads the viewer's eye to the next, and the total sequence completes in under a second. Compare this to a slideshow where everything appears simultaneously — the eye has nowhere to land, and the viewer's attention fragments.

Why Physics-Based Animation Wins

CSS transitions and keyframe animations define motion in terms of time: "move from A to B over 300ms with ease-out." Spring animations define motion in terms of energy: "this object is pulled toward B with stiffness K and resisted by damping D." The difference is profound:

  • Interruption: Retarget a CSS transition mid-flight and you get a jarring jump or an awkward restart. Retarget a spring and it smoothly redirects — the velocity is preserved, and the new target simply changes the equilibrium point.
  • Proportionality: A time-based animation takes the same duration whether the distance is 10px or 1000px. A spring naturally takes longer for larger displacements, which matches human expectations.
  • Consistency: With springs, you define one set of parameters (stiffness, damping) and every animation — regardless of distance or direction — feels like it belongs to the same physical world.
When everything in the viewer obeys the same physics, the experience feels cohesive. The viewer stops noticing the animations and starts focusing on the product — which is exactly the point.

Performance Considerations

A cinematic viewer is only cinematic if it runs at 60 fps. The key constraints:

  • Minimize main-thread work: Spring calculations are cheap (a few multiplications per frame), but DOM updates are not. Batch all position updates into a single requestAnimationFrame callback. Use transform exclusively — avoid top, left, width, or height changes that trigger layout.
  • Promote layers: Elements that animate (the canvas, the spotlight overlay, the cursor, tooltips) should each live on their own compositor layer. This allows the GPU to composite them independently without repainting.
  • Image optimization: Each step's screenshot is a high-resolution image. Lazy-load upcoming steps, use modern formats (WebP, AVIF), and decode images off the main thread with createImageBitmap where supported.

The Cumulative Effect

No single technique here is revolutionary. Springs, GPU compositing, Bézier curves, and staggered animations are all well-understood tools. The magic is in their composition: when every element in the viewer moves according to the same physical model, arrives in a deliberate sequence, and runs at a locked 60 fps, the demo stops feeling like a tool and starts feeling like an experience. That perception gap — between "slideshow" and "cinematic" — is the difference between a prospect bouncing and a prospect booking a call.

Ready to create your first interactive demo?

Upload a product recording and get a shareable, interactive demo in minutes. No design work required.

Get started free