4.5相机动画与切换


文档摘要

4.5相机动画与切换 Three.js 相机动画与切换:打造动态视角体验 4.5.1 相机动画基础 相机动画的核心在于随时间改变相机的属性,如位置 (position)、目标点 (lookAt) 和角度 (fov)。我们可以利用 Three.js 提供的 或直接使用 Tween.js 等第三方库来实现这些动画。 1. 使用 Tween.js 实现相机动画 Tween.js 是一个轻量级的 JavaScript 动画库,非常适合用于简单的相机动画。 首先,你需要引入 Tween.js 库。 然后,我们可以创建一个 Tween 对象来控制相机的属性变化。 代码详解: : 创建一个新的 Tween 对象,并指定要动画的属性(这里是 )。 : 设置动画的目标值和持续时间。

4.5相机动画与切换

Three.js 相机动画与切换:打造动态视角体验

4.5.1 相机动画基础

相机动画的核心在于随时间改变相机的属性,如位置 (position)、目标点 (lookAt) 和角度 (fov)。我们可以利用 Three.js 提供的 THREE.AnimationMixer 或直接使用 Tween.js 等第三方库来实现这些动画。

1. 使用 Tween.js 实现相机动画

Tween.js 是一个轻量级的 JavaScript 动画库,非常适合用于简单的相机动画。

首先,你需要引入 Tween.js 库。

<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/16.3.1/Tween.min.js"></script>

然后,我们可以创建一个 Tween 对象来控制相机的属性变化。

import * as THREE from 'three'; import TWEEN from '@tweenjs/tween.js'; // 创建场景、相机和渲染器 (省略) const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 设置相机初始位置 camera.position.set(0, 5, 10); camera.lookAt(0, 0, 0); // 创建一个目标位置 const targetPosition = { x: 5, y: 2, z: -5 }; // 创建一个 Tween 对象 const tween = new TWEEN.Tween(camera.position) .to(targetPosition, 2000) // 动画持续时间 2000ms .easing(TWEEN.Easing.Quadratic.InOut) // 使用缓动函数 .onUpdate(() => { camera.lookAt(0, 0, 0); // 保持相机朝向原点 }) .start(); // 动画循环 function animate() { requestAnimationFrame(animate); TWEEN.update(); renderer.render(scene, camera); } animate();

代码详解:

  • new TWEEN.Tween(camera.position): 创建一个新的 Tween 对象,并指定要动画的属性(这里是 camera.position)。

  • .to(targetPosition, 2000): 设置动画的目标值和持续时间。targetPosition 定义了相机最终的位置,2000 表示动画持续 2000 毫秒。

  • .easing(TWEEN.Easing.Quadratic.InOut): 应用一个缓动函数,使动画的开始和结束都比较慢,中间加速。Tween.js 提供了许多不同的缓动函数,可以根据需要选择。

  • .onUpdate(() => { camera.lookAt(0, 0, 0); }): 在动画的每一帧更新时执行的回调函数。这里确保相机始终朝向原点。

  • .start(): 启动动画。

  • TWEEN.update(): 在动画循环中调用 TWEEN.update() 来更新 Tween 对象的状态。

2. 使用 THREE.AnimationMixer 实现相机动画

THREE.AnimationMixer 通常用于骨骼动画,但也可以用于控制相机的属性。 需要创建一个 THREE.AnimationClip 对象来定义动画。

import * as THREE from 'three'; // 创建场景、相机和渲染器 (省略) const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 设置相机初始位置 camera.position.set(0, 5, 10); camera.lookAt(0, 0, 0); // 创建一个相机轨迹 const cameraTrack = new THREE.VectorKeyframeTrack( '.position', // 属性路径 [0, 1, 2], // 关键帧时间点 [0, 5, 10, // 关键帧位置 5, 2, -5, -3, 1, 2] ); const lookAtTrack = new THREE.VectorKeyframeTrack( '.lookAt', [0, 1, 2], [0, 0, 0, 1, 1, 1, -1, -1, -1] ); // 创建一个动画剪辑 const clip = new THREE.AnimationClip('cameraAnimation', 3, [cameraTrack]); // 创建一个动画混合器 const mixer = new THREE.AnimationMixer(camera); // 创建一个动画动作 const action = mixer.clipAction(clip); // 播放动画 action.play(); // 时钟 const clock = new THREE.Clock(); // 动画循环 function animate() { requestAnimationFrame(animate); const delta = clock.getDelta(); mixer.update(delta); // 更新动画混合器 camera.lookAt(0, 0, 0); // 确保相机始终朝向目标 renderer.render(scene, camera); } animate();

代码详解:

  • THREE.VectorKeyframeTrack: 用于定义相机位置和目标点的关键帧。第一个参数是属性路径,.position 表示相机的位置,.lookAt 表示相机要看向的目标点。第二个参数是关键帧的时间点,第三个参数是关键帧的值。

  • THREE.AnimationClip: 将关键帧轨迹组合成一个动画剪辑。

  • THREE.AnimationMixer: 用于控制动画的播放。

  • mixer.clipAction(clip): 创建一个动画动作,用于播放动画剪辑。

  • action.play(): 开始播放动画。

  • mixer.update(delta): 在动画循环中更新动画混合器。delta 是自上一帧以来经过的时间。

  • camera.lookAt(0, 0, 0): 确保相机始终朝向原点。 这里需要注意的是,lookAt 属性实际上并不存在,需要手动调用 lookAt 方法来更新相机的朝向。 更好的方式是使用 THREE.Object3D 作为 lookAt 的目标,并对该 Object3D 进行动画,然后让相机 lookAtObject3D

4.5.2 相机切换

相机切换允许你在不同的视角之间平滑过渡,从而增强场景的动态性和叙事性。

1. 简单切换

最简单的相机切换方法是直接更改 renderer.render() 中使用的相机对象。

import * as THREE from 'three'; // 创建场景、相机和渲染器 (省略) const scene = new THREE.Scene(); const camera1 = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const camera2 = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000); camera1.position.set(0, 5, 10); camera1.lookAt(0, 0, 0); camera2.position.set(10, 2, -5); camera2.lookAt(0, 0, 0); let currentCamera = camera1; // 默认使用 camera1 // 切换相机的函数 function switchCamera() { currentCamera = (currentCamera === camera1) ? camera2 : camera1; } // 绑定事件,例如点击事件,来触发相机切换 document.addEventListener('click', switchCamera); // 动画循环 function animate() { requestAnimationFrame(animate); renderer.render(scene, currentCamera); // 使用 currentCamera 渲染场景 } animate();

代码详解:

  • 创建两个相机对象 camera1camera2,并设置它们的位置和朝向。

  • currentCamera 变量跟踪当前使用的相机。

  • switchCamera() 函数切换 currentCamera 的值。

  • 在动画循环中,使用 currentCamera 渲染场景。

2. 平滑过渡

为了使相机切换更平滑,可以使用 Tween.js 来创建一个过渡动画。

import * as THREE from 'three'; import TWEEN from '@tweenjs/tween.js'; // 创建场景、相机和渲染器 (省略) const scene = new THREE.Scene(); const camera1 = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const camera2 = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000); camera1.position.set(0, 5, 10); camera1.lookAt(0, 0, 0); camera2.position.set(10, 2, -5); camera2.lookAt(0, 0, 0); let currentCamera = camera1; let isTransitioning = false; function switchCamera() { if (isTransitioning) return; // 如果正在过渡,则不执行 isTransitioning = true; const startPosition = currentCamera.position.clone(); const startRotation = currentCamera.quaternion.clone(); const targetCamera = (currentCamera === camera1) ? camera2 : camera1; const targetPosition = targetCamera.position.clone(); const targetRotation = targetCamera.quaternion.clone(); const tween = new TWEEN.Tween({ t: 0 }) .to({ t: 1 }, 1000) // 过渡时间 1000ms .easing(TWEEN.Easing.Quadratic.InOut) .onUpdate((obj) => { currentCamera.position.lerpVectors(startPosition, targetPosition, obj.t); THREE.Quaternion.slerp(startRotation, targetRotation, currentCamera.quaternion, obj.t); currentCamera.updateProjectionMatrix(); // 更新投影矩阵 }) .onComplete(() => { currentCamera = targetCamera; isTransitioning = false; }) .start(); } document.addEventListener('click', switchCamera); function animate() { requestAnimationFrame(animate); TWEEN.update(); renderer.render(scene, currentCamera); } animate();

代码详解:

  • isTransitioning 变量用于防止在过渡期间触发多次切换。

  • lerpVectors() 函数用于在两个向量之间进行线性插值,实现位置的平滑过渡。

  • THREE.Quaternion.slerp() 函数用于在两个四元数之间进行球面线性插值,实现旋转的平滑过渡。

  • currentCamera.updateProjectionMatrix(): 当相机属性发生变化后,需要更新投影矩阵,以确保场景正确渲染。

4.5.3 进阶技巧

  • 使用 THREE.CameraHelper: THREE.CameraHelper 可以帮助你可视化相机的位置、方向和视锥体,这对于调试相机动画和切换非常有用。

    const cameraHelper = new THREE.CameraHelper(camera); scene.add(cameraHelper);
  • 控制相机焦距 (fov): 通过动画改变相机的 fov 属性,可以模拟变焦效果。

  • 使用路径动画: 可以使用 THREE.CatmullRomCurve3 创建一个平滑的曲线路径,然后让相机沿着该路径移动。

  • 结合交互: 将相机动画和切换与用户交互结合,例如,当用户点击某个物体时,将相机移动到该物体附近。

4.5.4 总结

相机动画和切换是 Three.js 中创造引人入胜体验的重要组成部分。通过掌握这些技术,你可以引导用户的视线,讲述故事,并增强场景的交互性。 本文介绍了相机动画和切换的基础知识,并提供了详细的代码示例。希望这些信息能帮助你创建出更具吸引力的 Three.js 应用。

希望以上内容能够帮助你深入理解 Three.js 中的相机动画和切换。 记住实践是最好的老师,尝试修改这些代码示例,并探索更多可能性,你将能够创建出令人惊叹的 3D 体验。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U