【Three.js】第六章 Animations 动画

06.Animations动画

介绍

我们创建了一个场景,我们在代码末尾渲染了一次。这已经是不错的进步了,但大多数时候,您会想要为您的作品制作一些动态效果动画。
使用 Three.js 时,动画效果类似于定格动画。您移动对象,然后进行渲染。然后再移动对象一点,再做一次渲染。等等。在渲染之间移动对象越多,它们看起来移动得越快。
您正在查看的屏幕以特定频率运行。我们称之为帧率。帧率主要取决于屏幕,但计算机本身有局限性。大多数屏幕以每秒 60 帧的速度运行。如果你算一下,这意味着大约每 16 毫秒一帧。但是有些屏幕可以运行得更快,当计算机处理事情有困难时,它会运行得更慢。
我们想要执行一个函数,该函数将移动对象并在每帧上进行渲染,而不管帧速率如何。
这样做的本机 JavaScript 方法是使用window.requestAnimationFrame(...)方法。

设置

和以前一样,我们在启动器中拥有的只是场景中心的立方体。

使用 requestAnimationFrame

requestAnimationFrame没有办法在每一帧上运行代码。
requestAnimationFrame是将在下一帧执行我们提供的命令。但是,如果我们使用**递归死循环调用自身,**此函数requestAnimationFrame也用于在下一帧再次执行自己,那么最终将永远在每一帧执行这个函数。
创建一个名为的函数tick并调用该函数一次。在此函数中,用于window.requestAnimationFrame(...)在下一帧调用相同的函数:

/**
 * Animate
 */
const tick = () =>
{
    
    
    console.log('tick')

    window.requestAnimationFrame(tick)
}

tick()

就是这样。开始了无限循环。
我们可以在控制台上看到的,'tick’在每一帧上都调用了。如果您在高帧率的计算机上测试此代码,'tick’会以更高的频率出现。
您现在可以renderer.render(...)在该函数内移动调用并增加立方体rotation

/**
 * Animate
 */
const tick = () =>
{
    
    
    // Update objects
    mesh.rotation.y += 0.01

    // Render
    renderer.render(scene, camera)

    // Call tick again on the next frame
    window.requestAnimationFrame(tick)
}

tick()

恭喜,你现在有了一个 Three.js 动画。
问题是,如果你在高帧率的计算机上测试这段代码,立方体会旋转得更快,而如果你在较低的帧率下测试,立方体会旋转得更慢。

适配帧率 Date.now()

为了使动画适应帧率,我们需要知道自上次更新以来已经过了多少时间。
首先,我们需要一种测量时间的方法。在本机 JavaScript 中,您可以使用Date.now()获取当前时间戳:

const time = Date.now()

时间戳对应于自 1970 年 1 月 1 日(Unix 时间的开始)以来经过的时间。在 JavaScript 中,它的单位是毫秒。
现在需要的是将当前时间戳减去前一帧的时间戳,以获得我们可以调用的值,deltaTime并在为对象设置动画时使用该值:

/**
 * Animate
 */
let time = Date.now()

const tick = () =>
{
    
    
		// Time
    const currentTime = Date.now()
    const deltaTime = currentTime - time
    time = currentTime

    // Update objects
    mesh.rotation.y += 0.01 * deltaTime

    // ...
}

tick()

我们的旋转基于自上一帧以来所花费的时间,那么无论帧速率如何,每个屏幕和每台计算机的旋转速度都是相同的。

使用时钟 Clock

虽然这段代码并没有那么复杂,但 Three.js 中有一个名为Clock的内置解决方案来处理时间计算。
您只需Clock实例化一个clock变量并使用内置方法,如getElapsedTime(). 此方法将返回自时钟创建以来经过了多少秒。
您可以使用此值来旋转对象:

/**
 * Animate
 */
const clock = new THREE.Clock()

const tick = () =>
{
    
    
    const elapsedTime = clock.getElapsedTime()

    // Update objects
    mesh.rotation.y = elapsedTime

    // ...
}

tick()

您还可以使用tick来移动带有position属性的东西。如果你想把这两个属性结合起来,使用Math.sin(...)你会得到一个环形运动的几何体:

/**
 * Animate
 */
const clock = new THREE.Clock()

const tick = () =>
{
    
    
    const elapsedTime = clock.getElapsedTime()

    // Update objects
    mesh.position.x = Math.cos(elapsedTime)
    mesh.position.y = Math.sin(elapsedTime)

    // ...
}

tick()

显然,您可以使用这些技术为任何Object3D制作动画,例如相机:

扫描二维码关注公众号,回复: 15802833 查看本文章
/**
 * Animate
 */
const clock = new THREE.Clock()

const tick = () =>
{
    
    
    const elapsedTime = clock.getElapsedTime()

    // Update objects
    camera.position.x = Math.cos(elapsedTime)
    camera.position.y = Math.sin(elapsedTime)
    camera.lookAt(mesh.position)

    // ...
}

tick()

另一个可用的方法是getDelta(...),但除非您确切知道Clock类代码中发生了什么,否则不应使用它。使用它可能会弄乱您的动画,并且您会得到不需要的结果。

使用动画库 GSAP

有时您会想要以一种非常特殊的方式为您的场景制作动画,这将需要使用另一个库。动画库有很多,但最著名的是GSAP
要将 GSAP 添加到我们的项目中,我们可以使用 Node.js 提供的依赖管理器,称为npm.
在您的终端中(当服务器未运行或在同一文件夹上使用另一个终端窗口时),运行npm install --save [email protected]
--save参数将依赖项保存在 中,package.json因此如果我们执行npm install.
强制@3.5.1版本。我们使用这个版本是因为它是编写课程时使用的版本,但如果您愿意,可以通过删除@3.5.1来安装最新版本.
GSAP 现在在文件夹中可用node_modules/,我们可以将其导入我们的script.js

import './style.css'
import * as THREE from 'three'
import gsap from 'gsap'

// ...

使用 GSAP 的方法有很多种,我们可以用一门完整的课程来介绍它,但这不是本课程的目标。我们将简单地创建一个demo来测试。如果您已经知道如何使用 GSAP,那么它与 Three.js 的工作方式相同。
注释与先前动画相关的代码,但保留tick功能与渲染。然后你可以使用以下方法创建我们所说的补间(从 A 到 B 的动画)gsap.to(...)

/**
 * Animate
 */
gsap.to(mesh.position, {
    
     duration: 1, delay: 1, x: 2 })

const tick = () =>
{
    
    
    // Render
    renderer.render(scene, camera)

    // Call tick again on the next frame
    window.requestAnimationFrame(tick)
}

tick()

GSAP 有一个内置的requestAnimationFrame,所以你不需要自己更新动画,但是,如果你想看到立方体移动,你需要在每一帧上继续渲染你的场景。

选择正确的解决方案

至于原生JS和动画库的选择,看你想达到什么效果。如果您要创建一个永远旋转的旋转木马,则不需要任何库。但是如果你想制作动画,例如剑的挥动,我更推荐你用别的动画库实现。

猜你喜欢

转载自blog.csdn.net/m0_68324632/article/details/130790448
今日推荐