Click object to zoom in, click anywhere outside of object to reverse zoom/animation

Ive pretty much got this working but having an issue when adding multiple objects, currently I’m using a gsap animation to zoom in on the object when you click it, and another gsap animation to zoom back to the original camera settings when you click anything except the object. When adding more than one clickable object this doesnt work because if you are already zoomed in on an object, if you click another one it triggers the animation to zoom back to the original camera settings.

Is there a better way to zoom in on an object and then revert back to the original camera settings when you click outside of the object, which would also allow you to click another object when already zoomed in, and the camera just moves across to the next object without first zooming out?

//Zoom
const zoomInTimeline = (x, y, z, zoomOutFactor = 0) => {
	let tl = gsap
		.timeline({ defaults: { duration: 1.5, ease: "expo.out", onUpdate: function() {controls.enabled = false;}} })
		.to(controls.target, { x, y, z})
		.to(camera.position, { x:4, y:2, z: 2 },0)
        
		// .to(group.rotation, { x: 0, y: 0 }, 0);
};

//Raycaster
var mesh=[];

const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2()

function onClick(event) {
	event.preventDefault();

	mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
	mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

	raycaster.setFromCamera( mouse, camera );

	var intersects = raycaster.intersectObjects( scene.children, true );

    //Click Tree006 to focus
	if ( intersects.length > 0 && intersects[0].object.name==="Tree006") {
        var object = intersects[0].object;
        zoomInTimeline(mesh["Tree006"].position.x, mesh["Tree006"].position.y, mesh["Tree006"].position.z, 5);

    console.log( 'Intersection:', intersects[ 0 ] );
	}

    //Click anywhere outside of object to leave focus
    if ( intersects.length > 0 && intersects[0].object.name!=="Tree006") {
        var object = intersects[0].object;
	    gsap.to( camera.position, {
            duration: 1, // seconds
            x: 6,
            y: 4,
            z: 4,
            onUpdate: function() {
                controls.enabled = true;
                // controls.enableRotate = true;
                
            }
        } );
	}

How about leftt-clicking (an object) for Zoom-In, and right-clicking (anywhere) for Zoom-out?

Hmm Its not very intuitive, I think users would get confused.

What im trying to achieve is possible (I just dont know how), see this example - https://madbox.io/

It’s just not intuitive to click into an object with the left mouse and then have to figure out that to get out of that locked zoomed camera, you have to right click?! When have you ever had to right click out of something on a website??

That part seems to be at the core of the problem.

Do you really believe, that clicking outside of the previously clicked object is any more intuitive?!

yes 100% clicking outside of the clicked object to revert to previous camera view is way more intuitive. For example the website I linked you to in my previous reply - https://madbox.io/

Another example, if a modal is displayed on a website, 99% of the time you will click outside of the modal to close it (the other 1% will require the user to click “close” or “X”), it would NEVER require a right click.

Go ahead. I wish you all the best.

I think your just missing a bit of state management.

Add a variable outside the click function that keeps track if you already zoomed in. This variable is set to true when zooming in or zoomed in.

Before zooming out, check if another object was intersected. If true, change camera to that object. Otherwise, zoom out and set the variable to false.

Hope this makes sense

1 Like

Perfectly. The thread opener is using modes (Zoomed-In, Overview) without being aware of it. And users will be confused, regardless of method chosen for mode-switch, because apparently nothing tells them which mode they’re in.