Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

JS Animation API

25 views
Skip to first unread message

Robert O'Callahan

unread,
May 28, 2009, 7:13:46 PM5/28/09
to
I might as well get this discussion started now...

We need a way to give the browser control over animation frame rates and
the timing of when animations actually draw. Having everyone doing their
own setTimeout()-based animation is terribly inefficient; basically if
there are 5 independent animations each wanting repainting 50 times a
second, then we'll try to repaint 5*50=250 times a second. We should
only repaint 20 times a second. Actually, we should repaint N times a
second where N is chosen by the browser to be no higher than the user's
screen refresh rate.

We will add support for declarative animations (SMIL/SVG Animation and
CSS Transitions). However, they will never be flexible enough for all
use cases, so we need to support scriptable animation well. If we can
easily retrofit existing JS animation libraries to use the new
facilities, that would be ideal.

So I propose the following API:
1) window.mozRequestAnimationFrame(): Signals that an animation is in
progress, and requests that the browser schedule a repaint of the window
for the next animation frame, if the window is visible.
2) The browser will fire a mozBeforePaint event at the document root
element (bubbling to document and window) before we repaint the window.
Animation libraries should register an event handler that checks the
current time, and updates the DOM/CSS state to show that point in the
animation. If the animation has not ended, the event handler should call
window.mozRequestAnimationFrame() again to ensure another frame will be
scheduled in a timely manner.

I considered having window.mozStartAnimation() and
window.mozEndAnimation() calls instead of having to call
mozRequestAnimationFrame() repeatedly, but I worry that people would
forget (or fail) to call mozEndAnimation() and we'd have to keep firing
the event many times a second. With mozRequestAnimationFrame(), if the
animation event listener hits an exception or fails for some other
reason, animation stops.

At every frame, the implementation will apply built-in animations (SMIL,
CSS Transitions, etc), then fire the mozBeforePaint event, then flush
style changes and reflows, and then repaint whatever's changed.

One nice feature is that if the window is not visible (e.g., hidden
tab), we will not need to schedule any animation frames. So
mozBeforePaint may not ever fire.

My suggestion is that we prototype this for chrome and then if it looks
good we should propose it via some standards group as an API for Web
content.

Rob

Robert O'Callahan

unread,
May 28, 2009, 7:20:44 PM5/28/09
to
On 29/5/09 11:13 AM, Robert O'Callahan wrote:
> One nice feature is that if the window is not visible (e.g., hidden
> tab), we will not need to schedule any animation frames. So
> mozBeforePaint may not ever fire.

One question is whether canvas.drawWindow should update to the latest
animation frame if the window is hidden and we've been suppressing
animation in it. I think it should, so tab-preview-like stuff on hidden
tabs will actually work.

Rob

Robert O'Callahan

unread,
May 28, 2009, 7:33:27 PM5/28/09
to
Rob Arnold asked how "native" animations fit into this. Native
animations include smooth scrolling, animated images, video, SMIL, and
CSS Transitions.

Basically there will be an internal version of mozRequestAnimationFrame
on the root prescontext (the prescontext at the root of a tree of
documents). We probably don't need dynamic registration of event
listeners, so I'm planning to hardcode callbacks to each subsystem into
the "paint an animation frame" function on the root prescontext (which
all painting will be going through, actually).

Rob

Ben Galbraith

unread,
May 29, 2009, 3:02:32 AM5/29/09
to
On May 28, 4:13 pm, Robert O'Callahan <rob...@ocallahan.org> wrote:
> 1) window.mozRequestAnimationFrame(): Signals that an animation is in
> progress, and requests that the browser schedule a repaint of the window
> for the next animation frame, if the window is visible.

Not necessary to specify resolution of animation? Any perf. benefit if
I request only 10 fps for an animation?

Robert O'Callahan

unread,
May 29, 2009, 8:51:47 PM5/29/09
to

Some benefit if you're the only animation. But if there's another 50fps
animation running in the same window there probably isn't a lot of perf
benefit to running yours slower.

Is there a reason to want a low frame rate, other than performance? I
would prefer to leave performance tuning of the frame rate to the
browser. We have much more information than the Web. We could, for
example, tune the frame rate so that we spend at most 50% of the time
doing painting and associated animation work, across all visible pages
and animations, if we think that's a good idea.

Rob

Justin Dolske

unread,
May 30, 2009, 2:06:27 AM5/30/09
to
On 5/28/09 4:13 PM, Robert O'Callahan wrote:

> So I propose the following API:

>[...]

Sounds good to me; the animation effects I've done to date should all
work well with this scheme.

The only thing I can think of that might be a little awkward is if
someone wants to have an animation that consists of discrete steps (vs.
something continuous, like a fade or slide). Say, a second-hand ticking
on a clock, or something like our throbber icons. Maybe it's inefficient
but sufficient for such a usecase to simply hammer away at
mozRequestAnimationFrame(), and only do something when currentTime -
lastStep >= stepInterval. Or maybe for low-rate animations, good old
setInterval() is fine.

Justin

Chris Jones

unread,
May 30, 2009, 4:07:45 AM5/30/09
to Justin Dolske, dev-pl...@lists.mozilla.org

IMHO, |mozRequestAnimationFrame(fromNowMs=0)| seems like a good
extension to this API that handles your case. When your display is
visible, and |fromNowMs| is way higher than the interval between display
refreshes, there's no difference between it and |setTimeout()|. And
when your display isn't visible, the draw event doesn't need to be fired
at all; however, with |setTimeout()|, your "test the waters" events
would continue to run. It seems that this extension communicates more
information to the browser schedulers than |setTimeout()|.

(When 0 <= |fromNowMs| < displayRefreshInterval, there's no difference
between |fromNowMs| and "0".)

Cheers,
Chris

Axel Hecht

unread,
May 30, 2009, 4:09:08 AM5/30/09
to

I guess if someone tries to make it look like a stop motion animation.
Or other "early movie" impressions. Those would look more authentic at
an artificially slow framerate.

I can see Paul coming up with some sweet demos of that ;-)

Axel

Robert O'Callahan

unread,
Jun 1, 2009, 5:47:25 AM6/1/09
to
On 30/5/09 8:09 PM, Axel Hecht wrote:
> I guess if someone tries to make it look like a stop motion animation.
> Or other "early movie" impressions. Those would look more authentic at
> an artificially slow framerate.

Then you should use setTimeout instead of this new API.

Rob

Robert O'Callahan

unread,
Jun 1, 2009, 5:48:45 AM6/1/09
to
On 30/5/09 8:07 PM, Chris Jones wrote:
> IMHO, |mozRequestAnimationFrame(fromNowMs=0)| seems like a good
> extension to this API that handles your case. When your display is
> visible, and |fromNowMs| is way higher than the interval between display
> refreshes, there's no difference between it and |setTimeout()|. And when
> your display isn't visible, the draw event doesn't need to be fired at
> all; however, with |setTimeout()|, your "test the waters" events would
> continue to run. It seems that this extension communicates more
> information to the browser schedulers than |setTimeout()|.

Yeah, that could be a good extension. I'm not convinced it's actually
worth having though.

Rob

Neil

unread,
Jun 1, 2009, 7:57:49 AM6/1/09
to
Robert O'Callahan wrote:

Couldn't you achieve the same effect by calling mozRequestAnimationFrame
from your setTimeout function?

--
Warning: May contain traces of nuts.

Karl Tomlinson

unread,
Jun 1, 2009, 9:03:45 PM6/1/09
to

Perhaps it should.

But for tab-preview, there may be an argument for capturing the
page as it was last seen, as that might be most helpful to a user
looking for a recently used tab. That could be handled in the
tab-preview implementation though.

Justin Dolske

unread,
Jun 1, 2009, 9:47:31 PM6/1/09
to
On 5/30/09 1:07 AM, Chris Jones wrote:

> IMHO, |mozRequestAnimationFrame(fromNowMs=0)| seems like a good
> extension to this API that handles your case.

I guess one worry with this would be script expecting the updates to
come at roughly the specified interval, and then being surprised if
another animation appears on the page that asks for high-rate updates.

You could avoid that by making the API more like setInterval()
(specifically, having a callback instead of shared event), though then
the browser side of the implementation gets more complex... Meh.

Justin

Daniel Holbert

unread,
Jun 1, 2009, 9:51:35 PM6/1/09
to
On 05/28/2009 04:20 PM, Robert O'Callahan wrote:
> On 29/5/09 11:13 AM, Robert O'Callahan wrote:
>> One nice feature is that if the window is not visible (e.g., hidden
>> tab), we will not need to schedule any animation frames. So
>> mozBeforePaint may not ever fire.
>
> One question is whether canvas.drawWindow should update to the latest
> animation frame if the window is hidden

One related problem -- if we don't schedule animation frames for hidden
SVG content, then as far as scripts are concerned, that content would
all appear "paused" as long as it's in the background. This could cause
problems if the script expects things to be animating.

For example, suppose we have a SMIL-animated SVG document in a
background tab, and suppose this document contains embedded Javascript
that periodically queries the computed style & reacts to it somehow. It
would be quite confusing, from the script's perspective, if computed
style values erratically started & stopped changing (for extended
periods of time) as the user selects different tabs.

Mike Shaver

unread,
Jun 1, 2009, 9:55:01 PM6/1/09
to dev-pl...@lists.mozilla.org
On Mon, Jun 1, 2009 at 9:03 PM, Karl Tomlinson <moz...@karlt.net> wrote:
> But for tab-preview, there may be an argument for capturing the
> page as it was last seen, as that might be most helpful to a user
> looking for a recently used tab.  That could be handled in the
> tab-preview implementation though.

For a lot of cases, the last time we saw the tab was while it was
still loading, which is why the user switched away to another tab to
wait.

The user wants to find the thing that they'll get -- picking something
from the preview and then getting something entirely different when
you see it seems like an unpleasant bait-and-switch.

Mike

Mike Shaver

unread,
Jun 1, 2009, 10:04:00 PM6/1/09
to dev-pl...@lists.mozilla.org
On Mon, Jun 1, 2009 at 9:51 PM, Daniel Holbert <dhol...@mozilla.com> wrote:
> One related problem -- if we don't schedule animation frames for hidden SVG
> content, then as far as scripts are concerned, that content would all appear
> "paused" as long as it's in the background.  This could cause problems if
> the script expects things to be animating.
>
> For example, suppose we have a SMIL-animated SVG document in a background
> tab, and suppose this document contains embedded Javascript that
> periodically queries the computed style & reacts to it somehow.  It would be
> quite confusing, from the script's perspective, if computed style values
> erratically started & stopped changing (for extended periods of time) as the
> user selects different tabs.

I assumed that reading computed style would cause an eager
computation, just like reading various layout-dependent properties
from script causes an eager reflow to occur.

Mike

Robert O'Callahan

unread,
Jun 2, 2009, 6:55:23 AM6/2/09
to
On 2/6/09 1:51 PM, Daniel Holbert wrote:
> One related problem -- if we don't schedule animation frames for hidden
> SVG content, then as far as scripts are concerned, that content would
> all appear "paused" as long as it's in the background. This could cause
> problems if the script expects things to be animating.
>
> For example, suppose we have a SMIL-animated SVG document in a
> background tab, and suppose this document contains embedded Javascript
> that periodically queries the computed style & reacts to it somehow. It
> would be quite confusing, from the script's perspective, if computed
> style values erratically started & stopped changing (for extended
> periods of time) as the user selects different tabs.

I think that would be an incorrect assumption by the script. SMIL/SVG
Animation doesn't require us to use any particular frame rate, does it?

Rob

Robert O'Callahan

unread,
Jun 2, 2009, 6:56:44 AM6/2/09
to

Yes, I think you could.

Rob

0 new messages