gsap.ticker
类型:对象
这个gsap.ticker
就像是GSAP引擎的心跳——它会在每次globalTimelineon everyrequestAnimationFrame
事件时更新,因此它完美地与浏览器的渲染周期同步。你可以添加自己的监听器以在每次更新后运行自定义逻辑(对游戏开发者非常有用)。可以添加任意数量的监听器。
基本示例
//add listener
gsap.ticker.add(myFunction);
function myFunction() {
//executes on every tick after the core engine updates
}
//to remove the listener later...
gsap.ticker.remove(myFunction);
回调参数
下列参数将传递给每个监听器函数:
- time : 数字- 自ticker启动以来的总时间(以秒为单位)。ticker的开始时间可能会因lagSmoothing而被推后。
- deltaTime : 数字- 自上一次tick以来经过的毫秒数。注意:你可以使用gsap.ticker.deltaRatio()来获取基于特定目标FPS的比例值。
- frame : 数字- 每次tick递增的帧(tick)编号。
所以你的监听器函数可以像这样设置来使用传递给它的这些参数:
function myFunction(time, deltaTime, frame) {
//makes use of time, deltaTime, and frame
}
.add() 的高级选项
在gsap.ticker.add()
:
- once(单次触发) : Boolean- 回调仅触发一次,然后自动移除
- prioritize : Boolean- 回调将被添加到队列顶部而不是底部,这意味着它将在队列中当前所有监听器之前触发。这对于希望在GSAP全局时间线之前执行回调的情况非常合适。之前队列中的任何监听器。这对于希望回调在GSAP全局时间线之前执行的情况非常合适。
// call myCallback once on the next requestAnimationFrame BEFORE the global timeline updates.
gsap.ticker.add(myCallback, true, true);
这些高级选项是在GSAP 3.10.0中添加的。
当标签页隐藏时限制频率
当用户切换到浏览器中的其他标签页时,ticker的更新频率会被大幅降低,以节省电池电量并减轻CPU负载(这是由于浏览器本身会降低requestAnimationFrame
事件分发的频率)。通常情况下,requestAnimationFrame
事件每秒发生大约60次,但这取决于浏览器和系统性能。一些现代设备以120Hz(每秒120次)更新。如果requestAnimationFrame
不受支持,ticker将自动回退使用普通的setTimeout()
循环。
Ticker 属性
- time : 数字- 自ticker启动以来的总时间(以秒为单位)。ticker的开始时间可能会因lagSmoothing而被推后。
- frame : 数字- 每次tick递增的帧(tick)编号。
gsap.ticker.fps()
要将ticker限制在特定帧率下,可以使用fps()
方法,如下所示:
// throttle the frames-per-second to 30
gsap.ticker.fps(30);
由于无法让浏览器加速原生的requestAnimationFrame
事件(通常为60fps),因此你不能做诸如gsap.ticker.fps(100)
(嗯,虽然你可以这样做,但仍然会以大约60fps运行)。但是,你可以做的是gsap.ticker.fps(30)
让ticker在必要时跳过节奏,尽可能接近30fps(或你设定的任何fps)。下文原始频率)。
gsap.ticker.deltaRatio()
(3.5.0版本新增)
这个gsap.ticker.deltaRatio()
方法返回自上次tick以来经过的时间作为一个基于特定目标FPS的比例值。例如,如果你执行gsap.ticker.deltaRatio(60)
但自上次tick以来实际经过的时间更像是以30fps运行(可能因为某些延迟),它将返回2
,从而可以轻松构建动态适应帧率变化的循环,如:
gsap.ticker.add(function () {
obj.x += 3 * gsap.ticker.deltaRatio(60); // rate of change will always be consistent even if the frame rate fluctuates
});
默认的fps
参数是60,因此除非你使用非60fps的目标帧率,否则你无需传入该参数。例如,如果你想基于30fps运行来获取比例值,可以执行gsap.ticker.deltaRatio(30)
这是一个演示由Blake Bowen提供。
gsap.ticker.lagSmoothing()
这个gsap.ticker.lagSmoothing()
方法同时用作GSAP的lag smoothing的getter和setter。
当CPU负载过高导致渲染之间出现延迟时会发生什么?
例如,想象一个应该立即开始的持续2秒的补间动画,但在第一次渲染该补间之前,CPU已经忙了一秒钟。大多数其他动画引擎(包括某些浏览器中的CSS动画)会向前推移起始时间以补偿延迟,但这种方法存在一个重大缺点:牺牲了同步性,并且可能导致间隔延迟混乱,使得当你试图整齐地交错播放动画时,它们会成群结组地输出。这显然不好。
GSAP一直采用严格的计时模型,优先保证完美的同步性,也就是说在上面的例子中,补间动画会渲染得就像在一秒钟的初始延迟之后它已完成了一半一样。基本上,每个动画引擎都不得不以某种方式支付延迟“税”——要么保持严格的时间控制和同步性,要么调整起始时间而失去同步性。
gsap.ticker.lagSmoothing()
提供了两者的最佳结合,当CPU过载时,它会在下一个tick调整核心计时机制,影响所有所有动画,因此一切保持完美同步。你可以设置阈值(毫秒),每当延迟时间超过此阈值时,引擎将调整内部时钟,使其表现得好像只经过了adjustedLag
经过的时间一样。即使你在gsap
上调用静态方法,此一项调整会影响GSAP中的所有内容(tweens、timeline
s 和delayedCall
s,因为它们都是由gsap
)。
核心的单一计时机制驱动的。threshold
设置为500
和adjustedLag
设置为33
(这些是默认值),只有当两次tick之间经过的时间超过500毫秒时才会发生调整,在这种情况下,它会表现得如同只过了33毫秒一样。所以如果CPU卡顿了整整2秒钟(哎呀!),你的动画在下次渲染时只会移动相当于33毫秒的时间,而不是直接跳跃2秒钟。*注意:这不会影响设备的性能或真实帧率——这只会影响当浏览器丢帧时GSAP的反应方式。*
此功能默认情况下已激活,使用threshold
500毫秒的阈值和adjustedLag
但如果你想更改设置,可以像这样操作:
//compensate only when 1000ms or more elapses between 2 ticks,//and then make it act like only 16ms elapsed:
gsap.ticker.lagSmoothing(1000, 16);
为什么不把数值设得非常低,比如都设为10?
因为这样做不会留出太多的缓冲空间,并且自然会让你的补间动画看起来运行得更慢(因为从技术上讲,如果几乎每次渲染时时间都被向前推动,它们的确会变慢)。还要注意,如果你有任何延迟调用(delayedCalls),它们也会受到影响。这其实是一件好事——它确保你可以依赖这些调用与引擎其余部分完美同步,但如果浏览器压力很大,每秒只渲染几帧,时间似乎真的会变慢,一个持续2秒的补间动画(或延迟调用)实际上可能需要8秒才能完成。
在大多数实际应用场景中,默认的500和33是理想选择,因为它们可以防止浏览器/CPU出现重大卡顿,同时允许帧率有轻微波动而不会不必要地减慢整体速度。
如果你想禁用滞后平滑处理,你可以简单地将其设置为0,就像gsap.ticker.lagSmoothing(0)
将阈值设置为一个极大的数值以使其永远不会被触发一样。