【Three.js】第六章 Animations 动画

2023-10-30

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制作动画,例如相机:

/**
 * 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 gsap@3.5.1
--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和动画库的选择,看你想达到什么效果。如果您要创建一个永远旋转的旋转木马,则不需要任何库。但是如果你想制作动画,例如剑的挥动,我更推荐你用别的动画库实现。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Three.js】第六章 Animations 动画 的相关文章

随机推荐

  • python爬虫可以做什么呢?

    1 收集数据 Python爬虫程序可用于收集数据 这是最直接和最常用的方法 由于爬虫程序是一个程序 程序运行得非常快 不会因为重复的事情而感到疲倦 因此使用爬虫程序获取大量数据变得非常简单 快速 2 数据储存 Python爬虫可以将从各个网
  • 【防攻世界】misc解题思路-学习笔记

    前言 靶场地址 防攻世界 一 Cat falg 丢进 kali 或者其他Linux系统直接 cat flag 二 MeowMeow可爱的小猫 这道题就很离谱 flag需要用010工具打开 拉到最后就可以看到文字样式 组起来就是 CatCTF
  • 【深度学习】去掉softmax后Transformer会更好吗?复旦&华为诺亚提出SOFT:轻松搞定线性近似...

    作者丨happy 编辑丨极市平台 导读 本文介绍了复旦大学 华为诺亚提出的一种新颖的softmax free的Transformer SOFT 所提SOFT显著改善了现有ViT方案的计算效率 更为关键的是 SOFT的线性复杂度可以允许更长的
  • OPC UA 学习笔记 Event,Condition和Alarm

    告警和事件在自动控制领域十分重要 它是保障系统安全运营的主要措施 OPC UA 设立了专门的一部分来规范告警和条件模型 OPC 10000 9 UA Part 9 Alarms and Conditions 事件 条件和告警是OPCUA 信
  • 编程常用英语词汇(一)

    编程常用英语词汇 一 编程对英语的要求自不必说 这个技能是必须的 在平时开发和学习过程中 就算你不能完全读懂这句话的意思 如果你了解其中某个关键词的意思 也能大概猜到这句话的意思 这样的话也能对你解决问题提供很大的帮助 这就是我为什么要进行
  • Paperreading之三Simple Baselines for Human Pose Estimation

    本次paper是coco2018关键点检测项目的亚军方案 方法非常的简洁明了 但是效果很惊艳 达到了state of the art paper的标题也是写了simple baseline 整篇paper包含一个sota的姿态估计和姿态跟踪
  • setchecked方法会触发OnCheckedChangeListener

    分享一下我老师大神的人工智能教程 零基础 通俗易懂 风趣幽默 还带黄段子 希望你也加入到我们人工智能的队伍中来 https blog csdn net jiangjunshow 转载请标明出处 http blog csdn net xx32
  • 模式识别机器学习PRML考前自测

    绪论 1 请介绍一下机器学习的整体框架 机器学习和模式识别基本一个东西 模式识别是工业界的称呼而已 机器学习是人工智能下属的子领域 用来辅助在大数据时代进行数据分析与数据管理 应用于数据挖掘工作 人工智能的其他子领域包括比如NLP CV等领
  • in module XXX. File is included in 4 contexts

    问题描述 整合SSM框架时 出现以下情况 原因分析 这四个配置文件应该位于同一个ApplicationContext下 解决方案
  • linux执行python程序实时重定向输出日志【-u参数】

    执行python程序的时候 不能实时输出 总是在执行完成之后再一次性的输出到日志中 对于长时间的 希望看到中间过程的情况 不是很方便 查了下是因为缓存的问题 u 表示不启用缓存 实时输出打印信息到日志文件 如果不加 u 则会导致日志文件不会
  • 框架到底是干什么用的?

    不用刻意地在设计中体现MVC 而是在不知不觉中写出符合优秀架构的代码 这应该是所有框架的共同目的 也应该是根本目的
  • 绝大部分人都理解错了HTTP中GET与POST的区别

    GET和POST是HTTP请求的两种基本方法 要说它们的区别 接触过WEB开发的人都能说出一二 最直观的区别就是GET把参数包含在URL中 POST通过request body传递参数 你可能自己写过无数个GET和POST请求 或者已经看过
  • keras神经网络入门:1.简单神经网络实现mnist识别,识别准确率高达89%

    第一步 导入相关模块 import tensorflow as tf from tensorflow keras import layers models from tensorflow keras datasets import mnis
  • 【深度学习】万字综述:用于深度神经网络加速的Shift操作

    作者丨科技猛兽 编辑丨极市平台 导读 如何同时满足减少可学习参数的数量以及维持computation memory access比值 你需要Shift操作 本文将详细介绍shift操作的具体方法 如何剪掉冗余的Shift操作 3种用于深度神
  • 【大模型系列 06】LLaMA-7B/13B for PyTorch 昇腾迁移

    源码链接 https gitee com ascend ModelZoo PyTorch tree master PyTorch built in foundation LLaMA 13B LLaMA 7B 13B for PyTorch
  • WIN10+Darknet自建简单数据集训练YOLOv3识别特定物体

    1 在darknet master build darknet x64 新建yolo obj cfg文件 可以直接复制yolov3 cfg 然后重命名为yolo obj cfg 然后就是修改这个文件内容了 将batch 改成64 batch
  • 类别不平衡

    类别不平衡产生原因 类别不平衡 class imbalance 是指分类任务中不同类别的训练样例数目差别很大的情况 产生原因 通常分类学习算法都会假设不同类别的训练样例数目基本相同 如果不同类别的训练样例数目差别很大 则会影响学习结果 测试
  • (八)BaseTableView的简单使用

    BaseTableView的简单使用 现在来说说另一个我封装比较重的UI组件 这个组件要实现什么效果呢 当你使用继承了BaseTableView的子类tableView后 只需要在使用这个类的控制器中传递给tableView一个数据数组 并
  • Vue3回到顶部(BackTop)

    效果如下图 在线预览 APIs 参数 说明 类型 默认值 必传 bottom BackTop 距离页面底部的高度 number string 40 false right BackTop 距离页面右侧的宽度 number string 40
  • 【Three.js】第六章 Animations 动画

    06 Animations动画 介绍 我们创建了一个场景 我们在代码末尾渲染了一次 这已经是不错的进步了 但大多数时候 您会想要为您的作品制作一些动态效果动画 使用 Three js 时 动画效果类似于定格动画 您移动对象 然后进行渲染 然