I’m experiencing unexpected behavior with camera rotation in my Three.js application after adding a custom zoom functionality using the mouse wheel. Initially, the camera and rotation worked flawlessly with TrackballControls
. However, after implementing a custom zoom that adjusts the camera position based on the cursor’s position, the rotation no longer behaves correctly.
window.addEventListener(‘wheel’, function(e) {
e.preventDefault(); // Prevent default scrolling
// Calculate NDC coordinates of the cursor
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (e.clientY / window.innerHeight) * 2 + 1;
// Update the Raycaster with the cursor position and camera
raycaster.setFromCamera(mouse, camera);
// Get the direction of the ray
const direction = raycaster.ray.direction.clone();
// Define zoom speed
const zoomSpeed = 100;
// Determine zoom direction based on deltaY
const zoomDirection = e.deltaY < 0 ? 1 : -1;
// Calculate zoom amount
const zoomAmount = zoomSpeed * zoomDirection;
// Move the camera along the ray direction
camera.position.addScaledVector(direction, zoomAmount);
// Optional: Limit camera distance
const minDistance = 100;
const maxDistance = 10000;
const distance = camera.position.length();
if (distance < minDistance) {
camera.position.setLength(minDistance);
} else if (distance > maxDistance) {
camera.position.setLength(maxDistance);
}
// Update camera projection matrix
camera.updateProjectionMatrix();
// Update TrackballControls to reflect the new camera position
trackballControls.update();
}, { passive: false });
function TrackEvent() {
if (!_mainSceneNode) {
console.error(“Main scene node is not defined.”);
return;
}
// Calculate bounding box and bounding sphere of the main scene node
const boundingBox = new THREE.Box3().setFromObject(_mainSceneNode);
const boundingSphere = boundingBox.getBoundingSphere(new THREE.Sphere());
// Initialize TrackballControls
trackballControls = new TrackballControls(camera, renderer.domElement);
trackballControls.rotateSpeed = 5.0;
trackballControls.zoomSpeed = 1.2;
trackballControls.panSpeed = 0.8;
// Enable/disable functionalities
trackballControls.noZoom = true; // Disabled because of custom zoom
trackballControls.noPan = false;
trackballControls.noRotate = false;
// Dynamic damping factor for smooth rotations
trackballControls.dynamicDampingFactor = 0.2;
// Set the pivot (target) to the center of the bounding sphere
trackballControls.target.copy(boundingSphere.center);
// Position the camera to view the entire model
const offset = boundingSphere.radius * 2;
camera.position.set(
boundingSphere.center.x + offset,
boundingSphere.center.y + offset,
boundingSphere.center.z + offset
);
camera.lookAt(boundingSphere.center);
// Update camera aspect ratio and projection matrix
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
// Update TrackballControls
trackballControls.update();
}
function render() {
requestAnimationFrame(render);
stats.update();
_lightHolder.quaternion.copy(camera.quaternion);
trackballControls.update();
renderer.render(scene,camera);
}