I want to zoom to an given object, so the camera is looking at it and the object is in the center of the window. What I do is this:
const lookAt = (target, camera) => {
new TWEEN.Tween(camera.position)
.to(
{
x: target.position.x,
y: 2, // a bit higher than the ground
z: target.position.z + 2 // a bit distance in front of the object
},
1500
)
.easing(TWEEN.Easing.Quadratic.InOut)
.start();
lookAt.scaleObject(target, 2);
}
// in animation loop: TWEEN.update();
I need to mention that I have a camera controller added to the scene as well:
const controls = new MapControls(camera, renderer.domElement);
controls.enableDamping = true;
Since I use a map controller, I think we can ignore the camera rotation, right?
At the moment the camera is somehow going to the target object, but its sometimes not in the center, sometimes camera is not looking at the object… and also the animation it self is laggy.
I tried also different ways but for sake of simplicity I don’t dump the code here…
what I want to achieve is this animation: https://teliabyen.telia.no/ (just about the camera animation to selected object)
What I actually wanted is that at any time of the tween stepps the camera does camera.lookAt(target); and also what needed to be fixed was, that the target of the orbitcontrol/ it’s center needed to be adjusted on each tween step:
Now it’s really doing almost what I want… BUT after finishing the nice tweening, the camera makes a small jump… I have no idea why… Like I see here on the forum I am not the only one having this problem.
actually I had the control.update() in the animation loop already.
may I present you the solution: (copied from everywhere, mainly from a post here on discourse, can’t find the link anymore, but I’ll update when I find it again) if you are one of those looking for a solution: how to zoom the camera and controler to a selected object in threejs with tweenjs: don’t use tween.js => it is a known tween.js issue that it somehow messes up rounding numbers in the last update loop which causes this “jump” on the end of the animation.
Use gsap:
const zoomAt = (target, camera)=>{
//use this code for a object size agnostic solution; build a bounding box around your object you want to zoom and get its size:
const aabb = new THREE.Box3().setFromObject( target );
const center = aabb.getCenter( new THREE.Vector3() );
const size = aabb.getSize( new THREE.Vector3() );
//now use gsap and not tweenjs.. never use tweenjs again. never.
gsap.to( camera.position, {
duration: 1,
x: center.x,
y: center.y+1, // place camera a bit higher than the object
z: center.z + size.z+1, // maybe adding even more offset depending on your model
onUpdate: function() {
camera.lookAt( target.position ); //important
}
} );
gsap.to( orbitControls.target, {
duration: 1,
x: center.x,
y: center.y, //set the center of the controler to the zoomed object
z: center.z , // no distance needed
onComplete: ()=>{
orbitControls.enabled = true; // activate the controler again after animation
}
} );
}
setInterval() is not the best solution. You want to use at least something like requestAnimationFrame() but even then you must manage all the tweening by yourself… sorry but you are without doubt the worst pirate I’ve ever heard of!
if throwing out tween in favour for gsap is an option please do so I had so many problems with orbit controls and tween so ended up using gsap
zooming looks like this in gsap:
if (intersects[0].object.name == “ObjectOne”) {
gsap.to(camera, {
duration: 2,
zoom: 1,
onUpdate: function () {
camera.updateProjectionMatrix();
},
});
}
you’ll need to use raycasting and lookAt as well