Using requestAnimationFrame inside requestIdleCallback - javascript

If I animate changes in the DOM from JS (e.g. changing the value of a node's textContent from 1 to 500), would it be better to use requestAnimationFrame or requestAnimationFrame within a requestIdleCallback?

If you want to animate some code, then use only requestAnimationFrame, if you want to perform an action only when the browser has nothing else to do anymore, then use requestIdleCallback.
To simplify things, let's consider that both requestAnimationFrame and requestIdleCallback are setTimeout calls, with variables timeout arguments.
requestAnimationFrame would then be setTimeout(fn, time_until_next_screen_refresh). fn will be called right before the page is painted to the screen. This is currently the best timer we have to make animations since it ensures we'll only do the visual modifications only once per actual frame, at the speed of what the monitor is able to render, thus at every frame, if our code is fast enough.
requestIdleCallback would be setTimeout(fn, time_until_idle). fn will be called as soon as the browser has nothing more to do. This can be right away, or in a few event loops iterations.
So while both have a similar API, they provide completely different features, and the only viable one for doing an animation is requestAnimationFrame, since requestIdleCallback has basically no link whatsoever with the rendering.

Related

What is the meaning of frame in requestAnimationFrame in JavaScript?

I am having hard time understanding what are frames in JavaScript. Is frame a data structure? Is it frames as in FPS or refresh rate? Is it a fixed-time slice of window like preemptive scheduling? Also, it the same article it says:
rAFs aren’t throttled for you if they take too long to execute.
What does this means?
I understand how setInterval can cause performance issues when callbacks are long running by basically pilling up too many callback in the queue to execute. Also, What is the relation of frame with event loop of call stack/thread of execution?
Every code which is dedicated to an animation should be executed with requestAnimationFrame. When you say requestAnimationFrame that means: as soon as a frame is ready to be rendered, execute the callback (which should move or transform elements based on the timestamp parameter), and then render the frame. That allows the code which is dedicated to the animation to be run exactly at the same rate than the screen framerate.
The CPU consumption of the animation is then adjusted to what the screen can display.
An usual pattern is to call requestAnimationFrame recursively:
function render(timestamp) {
// Move and transform things
requestAnimationFrame(render);
}
requestAnimationFrame(render);

Is it useful to make the drag of mousedragging happening inside requestAnimationFrame?

I have a dragging library which moves the element on every mousemove.
As we all know, mousemove fires quite often and thus forces the browser into repaints.
This could be solved, by do the actual moving in requestAnimationFrame.
Is it a useful thing to do? Will it increase performance and decrease paint events?
Are there any issues I didnt think off?
Depends on the browser and the use case.
It is now asked by the specs that browsers do threshold themselves UI events (among which the mouse events).
Implementations are encouraged to determine the optimal frequency rate to balance responsiveness with performance.
Chrome and Firefox do this, firing these events only at screen refresh rate, just before requestAniamtionFrame callbacks fire.
So in these browsers, you won't win anything by doing so, but you won't lose much either.
Safari still fires as many such events as the device emits, so in this browser you'll win by maintaining your own threshold.
(Note that if you wish to unleash this threshold, you'll need to use pointerevents instead.)
Now, this is useful to avoid uselessly calculating things that will get discarded by next calls before it can get painted.
The painting will always be throttled to the refresh rate of your screen (just after the requestAnimationFrame callbacks fire).
So it's up to you to determine if you wish to apply that threshold or not.
For instance it can make sense to update a list of points as fast as possible, but to wait the requestAnimationFrame callback to actually make DOM changes or draw anything.
From the little you said about your case, it seems though that you may indeed win by waiting for requestAnimationFrame callbacks, only because you may be modifying the box model of your CSSOM.

Why do you put requestAnimationFrame before the function body?

For as long as I have been writing for the canvas, I've always done the following:
function animate() {
//do stuff in the animation
requestAnimationFrame(animate);
}
Lately though, I have frequently seen it done this way:
function animate() {
requestAnimationFrame();
//do stuff in the animation
}
While I can of course see benefits for doing it my way, (mainly, if there's a bug it won't continue to call more frames) I have been unable to find any benefits for calling for the next frame first.
Does anyone have an explanation for this/possible benefits for doing it this way? Or, can you prove it shouldn't be done this way? A source is definitely needed, as I've seen it all over the web but no one can really give a concrete reason for it.
The placement of the rAF call is clearer if you keep in mind that requestAnimationFrame is just requesting a ride on the next animation processing cycle -- it's not actually triggering the animation processing cycle.
Calling for the next rAF frame immediately will give you the best chance of catching the very next rAF cycle execution.
For example, if your "stuff" takes about 3ms to execute and the next rAF cycle starts in 4ms then you might catch the next cycle in 4ms rather than the subsequent cycle in 4+16ms. It might seem impossible that you would miss the next rAF cycle since you have 4-3==1ms to spare (nearly an eternity for the cpu), but the system might schedule other things that eat up your 1ms margin (like garbage collection).
On the other hand, if your "stuff" averages 15ms to complete then put your rAF call at the end. Putting it last might miss an execution once & a while, but it is probably better than risking multiple "stuff"s piling up.
With this in mind, very generally, putting the rAF call at the end is safer at the occasional cost of a missed rAF cycle.

Calling update method vs having a setInterval

In my game engine, there are objects that need to be updated periodically. For example, a scene can be lowering its alpha, so I set an interval that does it. Also, the camera sometimes needs to jiggle a bit, which requires interpolation on the rotation property.
I see that there are two ways of dealing with these problems:
Have an update() method that calls all other object's update methods. The objects track time since they were last updated and act accordingly.
Do a setInterval for each object's update method.
What is the best solution, and why?
setInterval does not keep to a clock, it just sequences events as they come in. Browsers tend to keep at least some minor amount of time between events. So if you have 10 events that all need to fire after 100ms you'll likely see the last event fire well into the 200ms. (This is easy enough to test).
Having only one event (and calling update on all objects) is in this sense better than having each object set it's own interval. There may be other considerations though but for at least this reason option 2 is unfeasible.
Here is some more about setInterval How do browsers determine what time setInterval should use?
The best way I have found out to make a good update() function and keeping a good framerate and less load is as following.
Have a single update() method which draws your frame, by looping some sort of queue/schedule of all drawable object his own update() function which are added to this update event queue/ schedule. (eventlistener)
This way you don't have to loop all objects which are not scheduled for a redraw/update (like menu buttons or crosshairs). And you don't have an over abundance of intervals running for all drawable objects.
I recommend using the update() method over the setInterval.
Also, I would guess that the timing on the several setintervals running would be unreliable.
Another possibility, depending on what other things are happening in your game, using a bunch of separate intervals could introduce race conditions in the counting and comparing of scoring, etc
The proposed algorithms proposed are not exclusive to the related method. That is, you can use setInteval to call all the update methods, or you can have each object update itself by repeatedly calling setTimeout.
More to the point is that a single timer is less overhead than multiple timers (of either type). This really matters when you have lots of timers. On the other hand, only one timer may not suit because some objects might need to be updated more frequently than others, or to a different schedule, so just try to minimise them.
An advantage with setTimeout is that the interval to the next call can be adjusted to meet specific scheduling requirements, e.g. if one is delayed you can skip the next one or make it sooner. setInterval will slowly drift relative to a consistent clock and one–of adjustments are more difficult.
On the other hand, setInteval only needs to be called once so you don't have to keep calling the timer. You may end up with a combination.

Scheduling update "threads" in JS / WebGL

Currently, I am rendering WebGL content using requestAnimationFrame which runs at (ideally) 60 FPS. I'm also concurrently scheduling an "update" process, which handles AI, physics, and so on using setTimeout. I use the latter because I only really need to update objects roughly 30 times per second, and it's not really part of the draw sequence; it seemed like a good idea to save the remaining CPU for actual render passes, since most of my animations are fairly hardware intensive.
My question is one of best practices. setTimeout and setInterval are not particularly kind to battery life and CPU consumption, especially when the browser is not in focus. On the other hand, using requestAnimationFrame (or tying the updates directly into the existing render phase) will potentially enforce far more updates every second than are strictly necessary, and may stop updating altogether when the browser is not in focus or at other times the browser deems unnecessary for "animation".
What is the best course of action for updating, but not rendering content?
setTimeout and setInterval are not particularly kind to battery life and CPU consumption
Let's be honest: Neither is requestAnimationFrame. The difference is that RAF automatically turns off when you leave the tab. That behavior can be emulated with setTimeout if you use the Page Visibility API, though, so in reality the power consumption problems between the two are about on par if used intelligently.
Beyond that, though, setTimeout\Interval is perfectly appropriate for use in your case. The only thing that you may want to be aware of is that you'll be hard pressed to get it perfectly in sync with the render loop. You'll have cases where you may draw one too many times before your animation update hits, which can lead to minor stuttering. If you're rendering at 60hz and updating at 30hz it shouldn't be a big issue, but you'll want to be aware of it.
If staying perfectly in sync with the render loop is important to you, you could simply have a if(framecount % 2) { updateLogic(); } at the top of your RAF callback, which effectively limits your updates to 30hz (every other frame) and it's always in sync with the draw.

Categories