文章目录
- Three JS 中的动画
- window.requestAnimationFrame(fn)
- 基本代码
- 修改显示器刷新率的对比
- 基础的动画尝试
- 不同帧率导致动画速率不同
- 解决方案一:DeltaTime
- 解决方案2:Clock
- 方法3: 动画库 Gsap
- 如何选择方案?
Three JS 中的动画
了解如何生成动画,才能去创造出更丰富的场景,所以动画是很基本的知识!!首先需要了解一个JavaScript 的动画函数
window.requestAnimationFrame(fn)
window.requestAnimationFrame()
方法会告诉浏览器你希望执行一个动画。它要求浏览器在下一次重绘之前,调用用户提供的回调函数。
先来一组基础代码
基本代码
import * as THREE from 'three'
import gsap from 'gsap'
/**
* Base
*/
// Canvas
const canvas = document.querySelector('canvas.webgl')
// Scene
const scene = new THREE.Scene()
/**
* Base
*/
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
/**
* Sizes
*/
const sizes = {
width: 800,
height: 600
}
/**
* Camera
*/
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
camera.position.z = 3
scene.add(camera)
/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
/**
* 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()
此时运行项目,打开控制台就会看到一直再打印 tick
修改显示器刷新率的对比
我尝试修改显示器的刷新频率试一下,我从 170hz
调整到 60hz
,可以看到控制台打印的速率明显变慢
以下是 60Hz
的样子,比起 170Hz
,打印的速度慢了一些
说明 window.requestAnimationFrame(tick)
会根据刷新率的高低来处理回调函数的频率
基础的动画尝试
可以通过这个回调函数来试着做位移,旋转的动画
/**
* Animate
*/
// gsap.to(mesh.position, { duration: 1, delay: 1, x: 2 })
const tick = () =>
{
console.log('tick')
// update objects
mesh.rotation.x -= 0.01
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
不过,如果你的显示器帧率越高,那么这些动画的速度是越快的,因为在一秒钟内你有更多的 tick 函数的调用
不同帧率导致动画速率不同
我们来打印一下
/**
* Animate
*/
// gsap.to(mesh.position, { duration: 1, delay: 1, x: 2 })
let time = Date.now()
const tick = () =>
{
// console.log('tick')
let currentTime = Date.now()
let deltaTime = currentTime - time
time = Date.now()
console.log('deltaTime:>>', deltaTime)
// update objects
mesh.rotation.x -= 0.01
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
这个是 170Hz
的
这个是 60Hz
的
那么如何让不同刷新率的显示器,显示相同速度的动画呢?
解决方案一:DeltaTime
/**
* Animate
*/
// gsap.to(mesh.position, { duration: 1, delay: 1, x: 2 })
let time = Date.now()
const tick = () =>
{
// console.log('tick')
let currentTime = Date.now()
let deltaTime = currentTime - time
time = Date.now()
console.log('deltaTime:>>', deltaTime)
// update objects
mesh.rotation.x -= 0.001 * deltaTime
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
让我们来实验一下
看起来是有效果的!
解决方案2:Clock
// Clock
const clock = new THREE.Clock()
const tick = () =>
{
const elapsedTime = clock.getElapsedTime()
console.log('elapsedTime:>>', elapsedTime)
// update objects
mesh.rotation.x = elapsedTime * Math.PI * 0.5
renderer.render(scene, camera)
// Call tick again on the next frame
window.requestAnimationFrame(tick)
}
tick()
这个是对比图
再来试试正弦函数
方法3: 动画库 Gsap
gsap
自己就会调用动画帧,所以不用告诉 gsap
自行更新
但是渲染的结果(也就是 Render) 还是要自己维护,所以render 要放到回调里。
如何选择方案?
- 根据你的项目,你的熟练度
- 以及项目体积,性能的权衡