Animation duration and FPS

animation

#1

Hi,

I’m struggling with a case that I thought would be documented, but my researches gave nothing.

I have a single-app website based on React, and I have a Three.js scene in background of every page.
Whenever I navigate in the website, it triggers changes into the 3D scene, without reloading it.

And I have very specific animations that need to last exactly one second in order to be synced with the other parts of the website.
For instance, when I scroll down the camera moves to the bottom in order to give the illusion of going underground. But in the mean time, I also have HTML elements that moves from bottom to top, and their animations are handled with CSS.
So the two animations should occur and end at the same time.

BUT here’s my issue: what about screen’s frame rate?
My desktop computer’s screen runs at 60fps, but on an unplugged laptop the screen’s fps is limited to 30.

As the render loop is based on RequestAnimationFrame, which is bound to the screen’s frame rate, the 3D scene will update at different speeds on a desktop and an unplugged laptop.
So my animation takes 1s on my desktop, but 2s on a laptop.

People talk about Tween.js and the Animation API from Three.js, but no one speaks about the frame rate.
Is Tween.js handling this fps behavior?
Should I implement an fps calculation in order to update my scene?
How can I make consistent animations not depending on the variable frame rate?


#2

If the duration of your animation really depends on the frame rate, there is something wrong with your app. Normally animations are updated with a time delta value in order to ensures a consistent duration over different update frequencies. That means an animation of 1 seconds has always this duration, no matter how many times it was updated per second.

Yes, tween.js internally measures the time in order to ensure consistent duration.

No, try to work with THREE.Clock if you need time values for animation updates.


#3

Thanks @Mugen87. I finally stumbled upon this solution as I was doing tests with the THREE.Clock.

There is however a pitfall: what if you reload your page, change tab immediately and then come back after a few seconds?
The Clock.getDelta() will return something like 9, as 9 seconds have passed since the last render (because RequestAnimationFrame only fires when tab is on focus).

The solution I used is a Math.min(0.05, clock.getDelta()), as 0.05 is the average delta for a 20fps screen (which doesn’t exists so it can be considered as the slowest framerate).

Is my solution right or is there a workaround?


#4

Using a max delta value is okay. Another options is to use the Page Visibility API. I’m using it in a current project to avoid big time deltas and it works great.


#5

Thanks, great solution!