Hi all,
You may have noticed that we implemented a "Click and hold to rotate" hint on the first embed of your session:
I received an interesting request for a more visual and intuitive Zoom In / Zoom Out, for users who might not know how to zoom on different devices, or might not even realize that the viewer is in 3D
So, I wrote a quick script to do this with the Viewer API and attach it to zoom buttons. For my purposes, I decided to add a zoom method to the api object.
zoom( factor, [duration], [minRadius], [maxRadius] )

factor
: required, a multiplier for the camera distance from the origin/target. (e.g.1.5
will move the camera 50% farther away, and0.5
will move the camera 50% closer) 
duration
: optional, duration of the camera animation in seconds, default 2s 
minRadius
: optional, the minimum distance to target, default 0.1 
maxRadius
: optional, the maximum distance to target, default infinity
Here's the function.
WARNING: Trigonometry ahead
api.zoom = function( factor, duration, minRadius, maxRadius ) {
api.getCameraLookAt( function( err, camera ) {
if ( !err ) {
var currentPos = camera.position,
x = currentPos[ 0 ],
y = currentPos[ 1 ],
z = currentPos[ 2 ],
target = camera.target,
rho = Math.sqrt( ( x * x ) + ( y * y ) + ( z * z ) ),
phi,
theta;
if ( isNaN( minRadius ) ) {
minRadius = 0.1;
}
if ( isNaN( maxRadius ) ) {
maxRadius = Infinity;
}
if ( rho === minRadius  rho === maxRadius ) {
return;
}
rho = ( rho * factor );
if ( rho < minRadius && factor < 1 ) {
rho = minRadius;
}
else if ( rho > maxRadius && factor > 1 ) {
rho = maxRadius;
}
phi = Math.atan2( y, x );
theta = Math.atan2( ( Math.sqrt( ( x * x ) + ( y * y ) ) ), z );
x = ( rho * Math.sin( theta ) * Math.cos( phi ) );
y = ( rho * Math.sin( theta ) * Math.sin( phi ) );
z = ( rho * Math.cos( theta ) );
api.setCameraLookAt( [ x, y, z ], target, duration );
}
} );
};
Full demo attached: zoomdemo.html (5.6 KB)
Feedback welcome! A slider instead of two buttons would be a pretty cool improvement.
EDIT: I added minimum and maximum radii parameters. This is mostly to avoid buggy behavior when the radius approaches zero, but it can also be a feature to constrain the viewer (e.g. don't go inside the model)