Three.js BoxHelper for Dynamically Scaling Objects
This article explains how to accurately visualize the bounding box of
a Three.js object as its scale changes dynamically in real-time. You
will learn how to initialize BoxHelper and keep it
perfectly synchronized with a morphing or scaling 3D mesh within your
render loop.
The Problem with Dynamic Scaling
When you instantiate a BoxHelper in Three.js, it
computes the bounding box based on the target object’s current state.
However, if the target object scales, rotates, or translates during
runtime, the bounding box helper will not automatically adapt to these
changes. It remains static, resulting in an inaccurate representation of
the object’s spatial boundaries.
The Solution: Using boxHelper.update()
To keep the bounding box aligned with a dynamically scaling object,
you must call the .update() method on your
BoxHelper instance inside the animation render loop. This
forces Three.js to recalculate the object’s world-space bounds on every
frame.
Step-by-Step Implementation
- Create the Target Object: Define the mesh that will scale dynamically.
- Create the BoxHelper: Instantiate the helper, passing the mesh as the target.
- Add Both to the Scene: Ensure both the mesh and the helper are added to your scene.
- Update in the Loop: Scale your mesh and call the
helper’s
.update()method in your requestAnimationFrame loop.
Code Example
import * as THREE from 'three';
// 1. Setup scene, camera, and renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 2. Create the target mesh
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const myMesh = new THREE.Mesh(geometry, material);
scene.add(myMesh);
// 3. Create the BoxHelper
const boxHelper = new THREE.BoxHelper(myMesh, 0xffff00);
scene.add(boxHelper);
camera.position.z = 5;
// 4. The Animation Loop
function animate() {
requestAnimationFrame(animate);
// Dynamically scale the mesh over time
const time = Date.now() * 0.001;
const scaleFactor = Math.sin(time) + 1.5; // Cycles between 0.5 and 2.5
myMesh.scale.set(scaleFactor, scaleFactor, scaleFactor);
// CRITICAL: Update the BoxHelper to match the new scale
boxHelper.update();
renderer.render(scene, camera);
}
animate();How It Works
The BoxHelper internally references the target object’s
geometry and world matrix. When boxHelper.update() is
called:
- It updates the helper’s geometry to fit the current bounding box of the target object.
- It accounts for all transformations applied to the target, including
scale,position, androtation. - It handles complex object hierarchies, calculating the bounding box of the target and all of its children.