Skip to content
On this page

Zoom to a point in threejs orbit controls

TIP

There is now a built-in feature in three.js and webgi to zoom to cursor. Use OrbitControls.zoomToCursor to zoom to a specific point. This is useful to zoom to a specific point in the model.

The following way is similar but provides support for damping etc.

Recently came across a use-case for displaying a long 3d model(of a chain) where the important part(pendant) is at the bottom. Using the standard OrbitControls, we can look at the model when zoomed out, but the pendant is not visible after zooming in.

Orbit zoomed outOrbit zoomed in

Setting the target of the camera to the bottom of the model can solve this, but then we are just using half of the canvas to display the model.

A better solution is to move the target of the camera(orbit controls) down as we zoom in. This way, the model is always visible in the canvas.

typescript
const modelHeight = 10 // get from bounding box
const center = new Vector3(0, 0, 0) // center of the model
const orbit = viewer.scene.activeCamera.controls as OrbitControls

const offset = new Vector3(0,0,0)
const camera = orbit.object
camera.addEventListener('update', (ev)=>{ // or use 'update' event from the controls `controls`
    let distance = camera.position.distanceTo(center)
    distance = Math.max(0,distance-1.5) // 1.5 is any custom offset
    
    const targetDiff = orbit.target.clone()
    
    // move along the y-axis. You can move towards a specific point as well
    offset.y = -0.5 * distance * modelHeight;
    orbit.target.copy(center).add(offset)
    
    targetDiff.sub(orbit.target)
    camera.position.sub(targetDiff)
})

Here, viewer is an instance of ThreeViewer(from threepipe), or ViewerApp (from webgi or ijewel3d).

NOTE

'update' event is not present in standard three.js camera. It's part of webgi/threepipe extended camera. For vanilla three.js, call the update method manually to reset the target or use the event in OrbitControls.

Here's how it looks in action:

Jewelery Design and 3D Model by Facet of Love

Made with ❤️ using the awesome vitepress