Warm tip: This article is reproduced from stackoverflow.com, please click
3d angular three.js tween.js

ThreeJS Tween JS | Move AND Rotate the camera to an object smoothly

发布于 2020-04-05 00:22:47

When I click on an object I can move and rotate around it.

Here's the non-smooth code :

mouseEvents() {
  window.addEventListener('click', (event: MouseEvent) => {
    event.preventDefault()
    // Get the mouse position
    this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1
    this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

    this.raycaster.setFromCamera(this.mouse, this.camera)

    var intersects = this.raycaster.intersectObjects(this.scene.children, true)
    for (var i=0; i<intersects.length; i++) {
      // Look at the object and rotate around it
      this.controls.target.set( intersects[i].point.x, intersects[i].point.y, intersects[i].point.z )
      // Move to the object
      this.camera.position.x = intersects[i].point.x
      this.camera.position.y = intersects[i].point.y
      this.camera.position.z = (intersects[i].point.z) + 1000     
    }
  })
}

Now I want to do the exact same hing but rotating AND moving smoothly. After a bunch of reading on the internet I found TweenJS and used it. The problem is that I can move towards the object smoothly but I don't know how to look at the object and rotate around it smoothly.

Here's the smooth code :

mouseEvents() {
  window.addEventListener('click', (event: MouseEvent) => {
    event.preventDefault()
    // Get the mouse position
    this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1
    this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

    this.raycaster.setFromCamera(this.mouse, this.camera)

    var intersects = this.raycaster.intersectObjects(this.scene.children, true)
    for (var i=0; i<intersects.length; i++) {
      // Look at the object and rotate around it smoothly (using tweenjs I suppose)
      ????????????
      // Move to the object smoothly
      var position = this.camera.position;
      var target = { x : intersects[i].point.x, y: intersects[i].point.y, z: intersects[i].point.z + 1000 };
      var tween = new TWEEN.Tween(position).to(target, 2000);
      tween.easing(TWEEN.Easing.Linear.None)
      tween.start()
    }
  })
}
Questioner
William
Viewed
155
manthrax 2020-02-03 20:44

You probably need to add a camera.lookAt( yourTargetPoint ) somewhere in your render loop, or in the tweens custom update function.

var target = new THREE.Vector3()
mouseEvents() {
  window.addEventListener('click', (event: MouseEvent) => {
    event.preventDefault()
    // Get the mouse position
    this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1
    this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

    this.raycaster.setFromCamera(this.mouse, this.camera)

    var intersects = this.raycaster.intersectObjects(this.scene.children, true)
    for (var i=0; i<intersects.length; i++) {
      target.copy(intersects[i].point)
      var tween = new TWEEN.Tween(this.camera.position).to(target, 2000)
      tween.easing(TWEEN.Easing.Linear.None)
      tween.onUpdate(() => {
        this.camera.lookAt( target )
      })
      tween.start()
break; // BREAK HERE BECAUSE WE ONLY CARE ABOUT THE FIRST/AKA NEAREST COLLISION
    }
  })
}

You also need to make sure the camera is added to the scene. You can renderer with a camera that ISNT attached to the scene, but then its matrices wont get updated during the rendering phase, in which case you would have to call .updateMatrixWorld() to force update its matrices. But its easier to just scene.add(camera)