webdevpuneet.com

Babylon.js Orbit Camera Showcase — Animated Preset Angles Snippet

Babylon.js Orbit Camera Showcase · Media · Plain HTML, CSS & JS · Live preview

Copy & paste

Source Code

Requires
<div class="boc-stage">
  <div class="boc-head">
    <span class="boc-tag">Babylon.js · animated camera presets</span>
    <h2>Product Lineup</h2>
    <p>Drag to orbit freely, or jump to a preset angle — the camera tweens there, it never snaps.</p>
  </div>
  <canvas id="bocCanvas"></canvas>
  <div class="boc-presets">
    <button class="boc-btn" data-view="front">Front</button>
    <button class="boc-btn" data-view="top">Top</button>
    <button class="boc-btn" data-view="side">Side</button>
    <button class="boc-btn" data-view="hero">Hero angle</button>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Tweened camera presets
Alpha, beta, and radius animate together via BABYLON.Animation instead of snapping instantly.
Ease-in-out motion
A shared CubicEase easing function gives every preset move a cinematic accelerate/decelerate shape.
Live current-value keyframes
Frame 0 always reads the camera's current value, so transitions chain correctly from any state.
Clean tween interruption
scene.stopAnimation cancels in-flight transitions before starting a new one or on manual drag.
Clamped beta range
lowerBetaLimit/upperBetaLimit stop the camera flipping under the ground or to a useless top angle.
Subtle drag inertia
camera.inertia gives manual orbiting a small coast-and-settle rather than an abrupt stop.
Multi-object lineup
Three differently shaped, colored meshes arranged along x form a believable product row.
Active preset indicator
The clicked preset button stays highlighted until manual drag or another preset is chosen.

About this UI Snippet

Babylon.js Orbit Camera Showcase — Tweening a Camera Instead of Snapping It

Screenshot of the Babylon.js Orbit Camera Showcase snippet rendered live

A "view from the top" button that just sets camera.alpha = x; camera.beta = y; directly works, but it looks broken — the camera teleports instantly, which reads as a glitch rather than a deliberate cut. A showcase camera should move the way a cinematographer would move it: smoothly, over a believable duration, with easing. Babylon.js's Animation class is what makes that possible without hand-rolling a tween loop.

Why direct assignment isn't enough

camera.alpha, camera.beta, and camera.radius are just numbers on the camera object — assigning them directly changes the camera's spherical position for the *next rendered frame*, with zero interpolation in between. That's fine for initial setup, wrong for a "go to this preset" button.

Building a per-property Animation

For each of the three properties, this snippet builds a BABYLON.Animation:

var alphaAnim = new BABYLON.Animation('alphaAnim', 'alpha', frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);

The constructor's second argument, 'alpha', is the literal property name on the target object Babylon will animate — this is why the same Animation class works for meshes, lights, materials, or cameras: it just needs a property name and a target object with that property. setKeys() then defines the keyframes:

alphaAnim.setKeys([{ frame: 0, value: camera.alpha }, { frame: 45, value: target.alpha }]);

Frame 0 is always the camera's current live value, not a hardcoded starting point — this is what makes goToPreset() work correctly no matter where the camera currently is, including mid-transition to a different preset.

Easing, and why CubicEase in EASEINOUT mode

var easing = new BABYLON.CubicEase(); easing.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT); anim.setEasingFunction(easing); — without this, Babylon interpolates keyframes linearly, which looks mechanical for a camera move. Ease-in-out accelerates out of the starting angle and decelerates into the target, the same shape as a real camera operator's move, and is applied identically to all three animated properties so alpha, beta, and radius all arrive with the same timing character.

Running three animations on one target together

camera.animations = [alphaAnim, betaAnim, radiusAnim]; scene.beginAnimation(camera, 0, durationFrames, false, 1); — assigning an array to camera.animations and calling beginAnimation once runs all three simultaneously and in lockstep, since they share the same frame range and frame rate. This is simpler than three separate beginAnimation calls and guarantees they finish at exactly the same frame.

Interrupting an in-flight tween

stopActiveAnims() calls scene.stopAnimation(camera) before starting a new preset transition or the instant the user starts dragging manually. Without this, clicking a second preset mid-tween — or grabbing the camera while it's still animating — would leave two animations racing to control the same alpha/beta/radius values, producing visibly jittery, fighting motion.

Clamped, slightly inertial manual control

camera.lowerBetaLimit/upperBetaLimit stop the user orbiting all the way under the ground plane or to a useless top-down flip. camera.inertia = 0.82 gives manual drags a small coast-and-settle after release — not enough to feel loose, just enough that release doesn't feel like an abrupt stop, echoing the same "nothing in this scene should snap" philosophy as the preset tweens.

Reusing it

This preset-tween pattern applies to any showroom, architectural walkthrough, or configurator that needs "jump to this named view" buttons. Pair it with a Babylon.js Spinning Product Viewer for continuous idle rotation instead of discrete preset stops.

Step by step

How to Use

  1. 1
    Add the Babylon.js CDNInclude the babylon.js UMD build for the global BABYLON namespace.
  2. 2
    Paste HTML, CSS, and JSA three-object product lineup renders on a ground plane with an orbit camera.
  3. 3
    Drag to orbit freelyattachControl handles manual rotation with a touch of inertia via camera.inertia.
  4. 4
    Click a preset buttonFront, Top, Side, and Hero angle each tween the camera there over 45 frames with easing.
  5. 5
    Click a preset mid-tweenThe in-flight animation is stopped and a new one starts cleanly from the current position.
  6. 6
    Drag manually mid-tweenStarting a drag cancels the active preset animation so it never fights your input.

Real-world uses

Common Use Cases

Virtual showrooms
Move between named camera angles on a product lineup, with alpha, beta and radius animating together instead of snapping.
Architectural walkthroughs
Present preset views of an interior or building, using a shared CubicEase so every move feels like a deliberate cinematic cut.
Configurator step transitions
Move the camera to the relevant part of a product as each configuration step begins, using the live current value as frame zero.
Babylon.js animation reference
Study BABYLON.Animation tweens, and how scene.stopAnimation cleanly cancels an in-flight move before the next one starts.
Camera choreography prototypes
Extend the preset buttons into scripted fly-throughs, with durationFrames and frameRate controlling how long each transition takes.

Got questions?

Frequently Asked Questions

Setting them directly changes the camera position instantly on the next render, with no interpolation -- the camera would teleport to the new angle, which looks like a glitch rather than a deliberate transition. Wrapping each property in a BABYLON.Animation and calling scene.beginAnimation() interpolates smoothly across a chosen number of frames instead.

Each Animation's first keyframe (frame 0) is set to the camera's current live value -- camera.alpha, camera.beta, camera.radius -- read at the moment the button is clicked, not a hardcoded prior position. That guarantees the tween always starts from wherever the camera actually is.

goToPreset() calls stopActiveAnims(), which calls scene.stopAnimation(camera) before building the new animations. That cancels whatever transition was still running so the new one starts cleanly from the camera's current (mid-transition) position, rather than the two animations fighting to control the same properties.

Linear interpolation between keyframes moves at a constant angular speed the entire transition, which feels mechanical for a camera move. Ease-in-out accelerates away from the start and decelerates into the end, matching how a real camera operator would perform the same move, and it is applied identically to alpha, beta, and radius so all three arrive with matching timing.

beta is the vertical polar angle of the orbit. Without limits, dragging far enough would let the camera orbit underneath the ground plane or flip to a disorienting straight-down angle. Clamping beta to a sensible range keeps every manually reachable angle looking intentional.

Set up the engine, scene, camera, meshes, and preset definitions once inside a useEffect (React) or onMounted (Vue), and expose a goToPreset function via a ref or emitted event that UI buttons call -- the animation logic itself needs no changes since it operates directly on the camera instance, not component state.