您如何保持让相机平稳地移动到新位置,同时仍然注视目标?

How do you maintain make a camera move to a new position smoothy while still looking at a target?

在此 中,我询问了如何将相机移动到相对于目标的不同位置。一位非常善良的绅士@TheJim01 提供了一个非常好的答案。

但是,我遇到了这样的问题,即在我移动相机后,相机会旋转并奇怪地定位。

保持相机旋转并保持其对目标的平稳视野的策略是什么?

平滑移动相机的更好方法是创建关键帧并将它们放置在由 emphasys 曲线定义的某种形式的时间轴中。

您可以使用任何补间库(Tween.js、GSAP)将相机从当前位置平滑地移动到球体顶部的位置。

此外,使用 THREE.Spherical() 计算最终点。并且不要忘记使用 .makeSafe() 方法。

body {
  overflow: hidden;
  margin: 0;
}
button{
  position: absolute;
  font-weight: bold;
}
<button id="moveUp">MOVE UP</button>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.5.1/dist/gsap.min.js"></script>
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js";
import { OrbitControls } from "https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js";

let scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x000000, 6, 15);
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

let controls = new OrbitControls(camera, renderer.domElement);
controls.maxDistance = 10;
controls.minDistance = 7;

let sphere = new THREE.Mesh(new THREE.SphereBufferGeometry(4, 36, 18), new THREE.MeshBasicMaterial({color: "aqua", wireframe: true}));
scene.add(sphere);

moveUp.addEventListener("click", onButtonClick);

let spherical = new THREE.Spherical();
let startPos = new THREE.Vector3();
let endPos = new THREE.Vector3();
let axis = new THREE.Vector3();
let tri = new THREE.Triangle();

function onButtonClick(event){
  spherical.setFromVector3(camera.position);
  spherical.phi = 0;
  spherical.makeSafe(); // important thing, see the docs for what it does
  endPos.setFromSpherical(spherical);
  
  startPos.copy(camera.position);
  
  tri.set(endPos, scene.position, startPos);
  tri.getNormal(axis);
  
  let angle = startPos.angleTo(endPos);
  
  let value = {value: 0};
  gsap.to(value, {value: 1, 
    duration: 2,
    onUpdate: function(){
      camera.position.copy(startPos).applyAxisAngle(axis, angle * value.value);
      controls.update();
    },
    onStart: function(){
      moveUp.disabled = true;
    },
    onComplete: function(){
      moveUp.disabled = false;
    }
    })
    .play();/**/
}

renderer.setAnimationLoop(()=>{
  renderer.render(scene, camera);
});
</script>