Re: The need to re-subscribe to requestAnimationFrame
On Mar 2, 2013 6:32 AM, Florian Bösch pya...@gmail.com wrote: You can also wrap your own requestAnimationFrameInterval like so: var requestAnimationFrameInterval = function(callback){ var runner = function(){ callback(); requestAnimationFrame(runner); }; runner(); } This will still stop if there's an exception thrown by callback, but it lets you write a cleaner invocation like so: requestAnimationFrameInterval(function(){ // do stuff }); It does not give you a way to stop that interval (except throwing an exception), but you can add your own if you're so inclined. Notably, you could not flexibly emulate requestAnimationFrame (single) via requestAnimationFrameInterval, so if you're gonna pick one semantic to implement, it's the former rather than the latter. For what it's worth, this would have been another (maybe better) way to address the concern that current spec tries to solve by requiring reregistration. I.e. we could have defined a id = requestAnimationFrameInterval(callback) cancelAnimationFrameInterval(id) Set of functions which automatically cancel the interval if an exception is thrown. That reduces the current risk that people write code that reregister at the top, and then has a bug further down which causes an exception to be thrown. / Jonas On Sat, Mar 2, 2013 at 3:15 PM, Glenn Maynard gl...@zewt.org wrote: On Sat, Mar 2, 2013 at 5:03 AM, David Bruant bruan...@gmail.com wrote: If someone wants to reuse the same function for requestionAnimationFrame, he/she has to go through: requestAnimationFrame(function f(){ requestAnimationFrame(f); // do stuff }) FYI, this pattern is cleaner, so you only have to call requestAnimationFrame in one place: function draw() { // render requestAnimationFrame(draw); } draw(); -- Glenn Maynard
Re: The need to re-subscribe to requestAnimationFrame
Btw. just as a sidenote, the document in document.requestAnimationFrame kind of matters. If you're calling it from the document that the canvas isn't in, then you'll get flickering. That may sound funny, but it's actually not that far fetched and is a situation you can run into if you're transfering a canvas to a popup window or iframe. With a requestInterval kind of function you're pretty much screwed in that case. On Fri, Mar 8, 2013 at 7:43 PM, Jonas Sicking jo...@sicking.cc wrote: On Mar 2, 2013 6:32 AM, Florian Bösch pya...@gmail.com wrote: You can also wrap your own requestAnimationFrameInterval like so: var requestAnimationFrameInterval = function(callback){ var runner = function(){ callback(); requestAnimationFrame(runner); }; runner(); } This will still stop if there's an exception thrown by callback, but it lets you write a cleaner invocation like so: requestAnimationFrameInterval(function(){ // do stuff }); It does not give you a way to stop that interval (except throwing an exception), but you can add your own if you're so inclined. Notably, you could not flexibly emulate requestAnimationFrame (single) via requestAnimationFrameInterval, so if you're gonna pick one semantic to implement, it's the former rather than the latter. For what it's worth, this would have been another (maybe better) way to address the concern that current spec tries to solve by requiring reregistration. I.e. we could have defined a id = requestAnimationFrameInterval(callback) cancelAnimationFrameInterval(id) Set of functions which automatically cancel the interval if an exception is thrown. That reduces the current risk that people write code that reregister at the top, and then has a bug further down which causes an exception to be thrown. / Jonas On Sat, Mar 2, 2013 at 3:15 PM, Glenn Maynard gl...@zewt.org wrote: On Sat, Mar 2, 2013 at 5:03 AM, David Bruant bruan...@gmail.com wrote: If someone wants to reuse the same function for requestionAnimationFrame, he/she has to go through: requestAnimationFrame(function f(){ requestAnimationFrame(f); // do stuff }) FYI, this pattern is cleaner, so you only have to call requestAnimationFrame in one place: function draw() { // render requestAnimationFrame(draw); } draw(); -- Glenn Maynard
The need to re-subscribe to requestAnimationFrame
Hi, If someone wants to reuse the same function for requestionAnimationFrame, he/she has to go through: requestAnimationFrame(function f(){ requestAnimationFrame(f); // do stuff }) I was wondering why it was the case. Other event-like mechanism do not require to re-subscribe after an event happened. Thanks, David
Re: The need to re-subscribe to requestAnimationFrame
Without having used it too much, I'd say it is because of the following: Imagine that you have a callback that does a lot of heavy rendering and the rAF returns AGAIN while // do stuff. Then you'd all of a sudden have an accumulating list of do stuff'ers that run in parallel - eating away CPU. There is no need to ask for the next available paint slot until the previous work is cleared out of the way. Correct me if I am wrong. - Lars On Sat, Mar 2, 2013 at 12:03 PM, David Bruant bruan...@gmail.com wrote: Hi, If someone wants to reuse the same function for requestionAnimationFrame, he/she has to go through: requestAnimationFrame(function f(){ requestAnimationFrame(f); // do stuff }) I was wondering why it was the case. Other event-like mechanism do not require to re-subscribe after an event happened. Thanks, David
Re: The need to re-subscribe to requestAnimationFrame
On 3/2/13 6:03 AM, David Bruant wrote: I was wondering why it was the case. Other event-like mechanism do not require to re-subscribe after an event happened. requestAnimationFrame was designed as a way for web pages to do animations without hogging CPU like they did with setTimeout/setInterval. The obvious choices for the behavior were a setTimeout-like behavior or a setInterval-like behavior. The former was chosen because the failure mode is that the animation stops when it shouldn't (which the author will notice and fix). The failure mode for the setInterval-like behavior is that the page keeps hogging CPU doing useless work once the animation has finished, which most authors do not notice, based on experience with setInterval. So of the two choices, the current behavior was a better fit for the goals of requestAnimationFrame. Note also that this is not an event-like mechanism necessarily; the request _causes_ the callbacks to fire. It also has other side-effects (for example, on Windows it switches the OS to high-resolution timers in many cases, increasing CPU usage and power consumption while there are live requestAnimationFrame listeners). -Boris
Re: The need to re-subscribe to requestAnimationFrame
On 3/2/13 6:45 AM, Lars Knudsen wrote: Imagine that you have a callback that does a lot of heavy rendering and the rAF returns AGAIN while // do stuff. Can't happen, unless the callback calls showModalDialog or something else that spins the event loop. -Boris P.S. Note that you can make your followup requestAnimationFrame call at the very beginning of the callback function and it will work fine too.
Re: The need to re-subscribe to requestAnimationFrame
On Sat, Mar 2, 2013 at 5:03 AM, David Bruant bruan...@gmail.com wrote: If someone wants to reuse the same function for requestionAnimationFrame, he/she has to go through: requestAnimationFrame(function f(){ requestAnimationFrame(f); // do stuff }) FYI, this pattern is cleaner, so you only have to call requestAnimationFrame in one place: function draw() { // render requestAnimationFrame(draw); } draw(); -- Glenn Maynard
Re: The need to re-subscribe to requestAnimationFrame
You can also wrap your own requestAnimationFrameInterval like so: var requestAnimationFrameInterval = function(callback){ var runner = function(){ callback(); requestAnimationFrame(runner); }; runner(); } This will still stop if there's an exception thrown by callback, but it lets you write a cleaner invocation like so: requestAnimationFrameInterval(function(){ // do stuff }); It does not give you a way to stop that interval (except throwing an exception), but you can add your own if you're so inclined. Notably, you could not flexibly emulate requestAnimationFrame (single) via requestAnimationFrameInterval, so if you're gonna pick one semantic to implement, it's the former rather than the latter. On Sat, Mar 2, 2013 at 3:15 PM, Glenn Maynard gl...@zewt.org wrote: On Sat, Mar 2, 2013 at 5:03 AM, David Bruant bruan...@gmail.com wrote: If someone wants to reuse the same function for requestionAnimationFrame, he/she has to go through: requestAnimationFrame(function f(){ requestAnimationFrame(f); // do stuff }) FYI, this pattern is cleaner, so you only have to call requestAnimationFrame in one place: function draw() { // render requestAnimationFrame(draw); } draw(); -- Glenn Maynard
WebPerformance WG and Visibility API, Yield and Continue, requestAnimationFrame
FYI, the Web Performance WG [WebPerf] intends to add Visibility API, Yield and Continue, requestAnimationFrame to their Charter when it is renewed/updated (in the next month or two): See their recent meeting minutes for some details: http://www.w3.org/2011/02/23-webperf-minutes.html#item01 http://www.w3.org/2011/02/23-webperf-minutes.html#item02 -Art Barstow [WebPerf] http://www.w3.org/2010/webperf/
Re: requestAnimationFrame
Hi, folks- This is just a quick note to let you all know that the topic of APIs for animation, both scripted and declarative, is one of the things that the FX Task Force [1] (a joint task force between the CSS and SVG WGs) is looking at, so we are following this thread with interest. From a Recommendation-track spec perspective, animation (and by extension, animation APIs and timing stuff) are already in scope for those groups, so we would like to standardize things there; obviously, we would want the continued participation of the WebApps WG participants as well. (I prefer to avoid more painful chartering discussions.) I'm not trying to cut off conversation here, I just wanted to make sure people were aware. [1] http://www.w3.org/Graphics/fx/ Regards- -Doug Schepers W3C Team Contact, SVG, WebApps, and Web Events WGs Gregg Tavares (wrk) wrote (on 11/15/10 6:03 PM): following in the footsteps of a previous thread http://lists.w3.org/Archives/Public/public-webapps/2009OctDec/0223.html I'd like to see if there is some consensus on this issue. Various people are anxious to see this happen in more browsers. A couple of questions came up for requestAnimationFrame (see http://weblogs.mozillazine.org/roc/archives/2010/08/mozrequestanima.html) One is, how should this api be used if I want an app to update at 10hz. It seems to be designed to assume I want the maximum frame rate. If I want to run slower would I just use setInterval(function() { window.requestAnimationFrame(); }, 100); // request frames at 10hz? That's fine if that's the answer But that brings up the next question. I'm in some alternate world where there is no Flash, instead all ads are implemented in Canvas. Therefore a site like cnn.com http://cnn.com or msnbc.com http://msnbc.com has 5 canvases running ads in each one. I don't really want all 5 canvases redrawn if they are not on the screen but the current design has requestAnimationFrame and beforePaint to be window level apis. That seems to have 2 issues. 1) All of them will get a beforePaint event even if most or all of them are scrolled off the visible area since there is only 1 beforePaint event attached to the window. 2) All of them will get beforePaint events at the speed of the fastest one. If one ad only needs to update at 5hz and other updates at 60hz both will update at 60hz. Do those issues matter? If they do matter would making both requestAnimationFrame and beforePaint be element level APIs solve it?
Re: requestAnimationFrame
How about this way of looking at it Goals 1) prevent programmer error 2) provide a good user experience (browser is responsive with lots of tabs) The solution to #1 as currently proposed is to guarantee that requestAnimationFrame will have it's callback called periodically, even if it's not visible. What's the solution to #2 in world where requestAnimationFrame is always called periodically? One solution was mentioned which is the browser can freeze the tab. I don't see how guaranteeing calling requestAnimationFrame once a second or so is compatible with freeze the tab. Wouldn't that break the contract? The problem I'm trying to address is not one of freezing a tab. That has issues. Sites like gmail, meebo, hotmail, yahoo mail, various twitter sites, etc all do setInterval or setTimeout processing to get the messages from the server. That's a reasonable thing to do with setTimeout and setInterval. Those are generally not very heavy operations. Getting a few k or 100k of text and processing it. You can't freeze them without breaking their functionality. requestAnimationFrame though is generally designed to be used for updating a canvas (2d or 3d) which will likely be heavy both in terms of CPU usage (drawing lots of lines/curves/images into the canvas) and in terms of memory usage (accessing lots of images). So, imagine you have a netbook and you've got 10-20 tabs open (less than I usually have open, YMMV). Imagine all the flash content (ads, video UIs) on those pages is done with canvas. Imagine there has been enough social pressure so that sites that used to use setInterval or setTimeout to update their canvas and therefore bog down the browser have switched to requestAnimationFrame. Now, given that the there's a promise to call the callbacks periodically, what would be your solution to fix the issue that the browser is running really slow since each time a callback comes in, 10s of megs of images have to get swapped in so they can be drawn into a canvas and then swapped back out when the next canvas gets it's animationFrame callback?
Re: requestAnimationFrame
On Wed, Nov 24, 2010 at 12:08 PM, Gregg Tavares (wrk) g...@google.comwrote: requestAnimationFrame though is generally designed to be used for updating a canvas (2d or 3d) which will likely be heavy both in terms of CPU usage (drawing lots of lines/curves/images into the canvas) and in terms of memory usage (accessing lots of images). So, imagine you have a netbook and you've got 10-20 tabs open (less than I usually have open, YMMV). Imagine all the flash content (ads, video UIs) on those pages is done with canvas. Imagine there has been enough social pressure so that sites that used to use setInterval or setTimeout to update their canvas and therefore bog down the browser have switched to requestAnimationFrame. You're really stretching my imagination here, but OK... Now, given that the there's a promise to call the callbacks periodically, what would be your solution to fix the issue that the browser is running really slow since each time a callback comes in, 10s of megs of images have to get swapped in so they can be drawn into a canvas and then swapped back out when the next canvas gets it's animationFrame callback? Actually I have one solution that I thought of the other day but forgot to post here: exponential backoff. Fire the first round of requestAnimationFrame callbacks in a hidden tab after 1 second. Fire the next round after 2 seconds, the next round after 4 seconds, etc. That guarantees that a) animation end activity is late by at most the duration of the animation (or one second, whichever is greater) b) if a tab is hidden for N seconds, we issue at most log2(N) requestAnimationFrame callbacks for it and c) we keep the simple promise that if requestAnimationFrame is called, we eventually fire the callback. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
* Robert O'Callahan wrote: Couldn't is never an issue here. You can always use setTimeout as a backstop to ensure that your end-of-animation code runs even if requestAnimationFrame never fires a callback. My concern is that authors are likely to forget to do this even if they need to, because testing scenarios are unlikely to test switching to another tab in the middle of the animation. The question was about what if you are guranteed that your script is run if the tab resumes, but not necessarily before that. In that case the code will always run, unless you did something crazy to detect whether to run the end of animation code (for instance, instead of checking if you are past 20 seconds, you check for whether you are between 20s and 30s to make your animation stop after 20s). That seems much less a concern than that the model here is unclear. If the model is you can this and then the browser will magically do one thing or another, we won't tell you the details then people would have a rougher time writing proper code than if the model was, say, Upon each call the callback must completely redraw everything and must not depend on state modifications made from within the callback in any way. It seems to me that end-of-animation problems are just another case of state transition problems, you might aswell change something between 5s and 10s and depend on that having been executed at 13s (say you may add a new element between 5s and 10s and fade it out again from 13s.) Personally I am already horrified by the hoops one has to jump through if one tries to synchronize audio playback and mozRequestAnimationFrame. -- Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de 25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/
Re: requestAnimationFrame
How about just running the callback once the tab becomes visible again? It will run, but just not unless there is reason to animate/paint. -Darin On Thu, Nov 18, 2010 at 6:08 PM, Robert O'Callahan rob...@ocallahan.orgwrote: I suppose we could have a variant API that explicitly means I don't care if the callback never gets called. I don't know what to call it, though. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
* Ojan Vafai wrote: On Fri, Nov 19, 2010 at 2:54 PM, Cameron McCormack c...@mcc.id.au wrote: Darin Fisher: I can imagine a situation where you have an animation that goes for, say, 10 seconds, and once the animation finishes something else happens. The 1 second maximum period seems useful in this case, because you might make the tab visible again for a long time, but you expect the “something else” to happen. It’s pretty natural to do the checking for whether the animation has gone past its end time within the callback. What's an acutal example where you might want this that couldn't just wait until the tab was visible again? This use-case doesn't seem very common. As you say, it's also probably not well met due to throttling. Well, if every event handler has If time is past my end time, clean up and unregister the handler logic, and you do not care about possible wait times when resuming the tab (for instance, the cleanup may load additional resources from the network which one might expect to load in the background), and find shared state manipulation far fetched (say, on disposal the handler may change cookies or local storage to indicate, say, you've already watched a full-screen ad on the page), then the only thing that could leak out of tabs, as far as my browser is concerned, is audio. To make up a simple case, you might have a visual progess indicator where the end time is determined by some network activity: when it finishes you get an audible done indicator and you bind the done logic to the animation handler, not the network handler. Obviously that does not address your question, since couldn't never applies here, you could always just use setTimeout and setInterval and burn cycles, or whatever else gurantees your script runs even when the tab is in the background, and implement the logic as you see fit. -- Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de 25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/
Re: requestAnimationFrame
* Robert O'Callahan wrote: Those are good goals, except I think we need to drill down into (c). Are people changing stuff at 15Hz for crude performance tuning, or for some other reason? There are many kinds of animations where you cannot easily interpolate between frames, so drawing in Ones requires a lot more effort than drawing in Twos. Add to that the abysmal performance of graphics in browsers and, sometimes worse, their plugins, and I would be more wondering why some set the framerate any higher (beyond Oh I thought that's what PAL/NTSC does, I read that in a forum). The default in Flash is 12 frames per second, which is your typical film rate in Twos. -- Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de 25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/
Re: requestAnimationFrame
On Sat, Nov 20, 2010 at 2:35 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote: Obviously that does not address your question, since couldn't never applies here, you could always just use setTimeout and setInterval and burn cycles, or whatever else gurantees your script runs even when the tab is in the background, and implement the logic as you see fit. Couldn't is never an issue here. You can always use setTimeout as a backstop to ensure that your end-of-animation code runs even if requestAnimationFrame never fires a callback. My concern is that authors are likely to forget to do this even if they need to, because testing scenarios are unlikely to test switching to another tab in the middle of the animation. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Thu, Nov 18, 2010 at 4:03 PM, Gregg Tavares (wrk) g...@google.comwrote: On (a) Take this page (http://boingboing.net) At the time I checked it today (6:55pm PST) it had 10 instances of flash running. O page load 3 were animating continuallty, 7 were idle. The 7 idle ones were all video with custom UIs. Of those 7, 6 of them will animate constantly once the video is finished advertising other videos to play. That means at any one time, if this was canvas based, 9 areas will be re-rendered by JavaScript on each animationFrame. It seems like giving the browser more info by tying these animation frames to specific elements would let the browser not call animationFrame callbacks unless the element it is tied to is on the screen and that would be a pretty good thing. If all 10 of those areas were re-rendering their ads all the time I suspect that page would get pretty slow, especially on netbooks. As it is, only 1-3 areas are ever visible at once. Yeah, that makes sense. Then I suggest adding requestAnimationFrame to elements, so you can call element.requestAnimationFrame(callback). I think there needs to be a guarantee that the callback is eventually called even if the element never becomes visible. People sometimes want to take action when an animation finishes. window.mozRequestAnimationFrame fires once per second even for hidden tabs for this reason. It's a little tricky to define exactly what it means for an element to be visible. I think we could probably leave that up to the UA without hurting interop. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Thu, Nov 18, 2010 at 12:45 AM, Robert O'Callahan rob...@ocallahan.orgwrote: On Thu, Nov 18, 2010 at 4:03 PM, Gregg Tavares (wrk) g...@google.comwrote: On (a) Take this page (http://boingboing.net) At the time I checked it today (6:55pm PST) it had 10 instances of flash running. O page load 3 were animating continuallty, 7 were idle. The 7 idle ones were all video with custom UIs. Of those 7, 6 of them will animate constantly once the video is finished advertising other videos to play. That means at any one time, if this was canvas based, 9 areas will be re-rendered by JavaScript on each animationFrame. It seems like giving the browser more info by tying these animation frames to specific elements would let the browser not call animationFrame callbacks unless the element it is tied to is on the screen and that would be a pretty good thing. If all 10 of those areas were re-rendering their ads all the time I suspect that page would get pretty slow, especially on netbooks. As it is, only 1-3 areas are ever visible at once. Yeah, that makes sense. Then I suggest adding requestAnimationFrame to elements, so you can call element.requestAnimationFrame(callback). I think there needs to be a guarantee that the callback is eventually called even if the element never becomes visible. People sometimes want to take action when an animation finishes. window.mozRequestAnimationFrame fires once per second even for hidden tabs for this reason. I see your point but I'm a little worried about adding that exception. Take the boingboing.net example again. There are 10 areas, 1 is on the screen, it's playing video. If once a second all 9 areas have their animationFrame callback called that video will probably glitch or stutter once a second. I suppose the UA can stagger the offscreen animationFrame calls but I just wonder if calling them at all when they are offscreen is really warranted. Or how about I've got boingboing.net in one tab (10 areas), techcrunch.comin another (4 areas), geekologie.com in a 3rd (7 areas), nytimes.com in a 4th (3 areas), add a few more and soon my machine will end up being bogged down making animationFrame callbacks to offscreen tabs. Is the solution to just keep calling each one less and less frequently? I'd prefer it if my under powered netbook wasn't spending it's time and battery rendering things offscreen ever if possible. Not only that, but as I add more and more tabs I'd like to be able to swap them out of memory, but if every second or 2 seconds or 10 seconds each one gets an animationFrame callback then it will be swapped back into memory. It's a little tricky to define exactly what it means for an element to be visible. I think we could probably leave that up to the UA without hurting interop. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Thu, Nov 18, 2010 at 11:21 AM, Gregg Tavares (wrk) g...@google.comwrote: On Thu, Nov 18, 2010 at 12:45 AM, Robert O'Callahan rob...@ocallahan.orgwrote: On Thu, Nov 18, 2010 at 4:03 PM, Gregg Tavares (wrk) g...@google.comwrote: On (a) Take this page (http://boingboing.net) At the time I checked it today (6:55pm PST) it had 10 instances of flash running. O page load 3 were animating continuallty, 7 were idle. The 7 idle ones were all video with custom UIs. Of those 7, 6 of them will animate constantly once the video is finished advertising other videos to play. That means at any one time, if this was canvas based, 9 areas will be re-rendered by JavaScript on each animationFrame. It seems like giving the browser more info by tying these animation frames to specific elements would let the browser not call animationFrame callbacks unless the element it is tied to is on the screen and that would be a pretty good thing. If all 10 of those areas were re-rendering their ads all the time I suspect that page would get pretty slow, especially on netbooks. As it is, only 1-3 areas are ever visible at once. Yeah, that makes sense. Then I suggest adding requestAnimationFrame to elements, so you can call element.requestAnimationFrame(callback). I think there needs to be a guarantee that the callback is eventually called even if the element never becomes visible. People sometimes want to take action when an animation finishes. window.mozRequestAnimationFrame fires once per second even for hidden tabs for this reason. I see your point but I'm a little worried about adding that exception. Take the boingboing.net example again. There are 10 areas, 1 is on the screen, it's playing video. If once a second all 9 areas have their animationFrame callback called that video will probably glitch or stutter once a second. I suppose the UA can stagger the offscreen animationFrame calls but I just wonder if calling them at all when they are offscreen is really warranted. Or how about I've got boingboing.net in one tab (10 areas), techcrunch.comin another (4 areas), geekologie.com in a 3rd (7 areas), nytimes.com in a 4th (3 areas), add a few more and soon my machine will end up being bogged down making animationFrame callbacks to offscreen tabs. Is the solution to just keep calling each one less and less frequently? I'd prefer it if my under powered netbook wasn't spending it's time and battery rendering things offscreen ever if possible. Not only that, but as I add more and more tabs I'd like to be able to swap them out of memory, but if every second or 2 seconds or 10 seconds each one gets an animationFrame callback then it will be swapped back into memory. I agree. What's the use case for animating hidden tabs (or canvases that are hidden)? One of the big problems with JavaScript based animations is that they have no way of knowing they should go idle when their window is hidden (in a background tab or otherwise). The same API used to rate-limit rendering could address the problem of hidden tabs too. -Darin It's a little tricky to define exactly what it means for an element to be visible. I think we could probably leave that up to the UA without hurting interop. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Fri, Nov 19, 2010 at 8:21 AM, Gregg Tavares (wrk) g...@google.comwrote: On Thu, Nov 18, 2010 at 12:45 AM, Robert O'Callahan rob...@ocallahan.orgwrote: I think there needs to be a guarantee that the callback is eventually called even if the element never becomes visible. People sometimes want to take action when an animation finishes. window.mozRequestAnimationFrame fires once per second even for hidden tabs for this reason. I see your point but I'm a little worried about adding that exception. Take the boingboing.net example again. There are 10 areas, 1 is on the screen, it's playing video. If once a second all 9 areas have their animationFrame callback called that video will probably glitch or stutter once a second. I suppose the UA can stagger the offscreen animationFrame calls but I just wonder if calling them at all when they are offscreen is really warranted. Or how about I've got boingboing.net in one tab (10 areas), techcrunch.comin another (4 areas), geekologie.com in a 3rd (7 areas), nytimes.com in a 4th (3 areas), add a few more and soon my machine will end up being bogged down making animationFrame callbacks to offscreen tabs. Is the solution to just keep calling each one less and less frequently? I'd prefer it if my under powered netbook wasn't spending it's time and battery rendering things offscreen ever if possible. Not only that, but as I add more and more tabs I'd like to be able to swap them out of memory, but if every second or 2 seconds or 10 seconds each one gets an animationFrame callback then it will be swapped back into memory. I'm only suggesting that we guarantee the callback is eventually called. You can throttle it to lower than 1Hz if you want. If you really want to save power you need to freeze apps completely anyway. Many apps are already using setTimeout all the time, and they won't all change. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Fri, Nov 19, 2010 at 10:46 AM, Darin Fisher da...@chromium.org wrote: I agree. What's the use case for animating hidden tabs (or canvases that are hidden)? One of the big problems with JavaScript based animations is that they have no way of knowing they should go idle when their window is hidden (in a background tab or otherwise). The same API used to rate-limit rendering could address the problem of hidden tabs too. Yes. As I mentioned, we do that in Firefox. Please read what I wrote above. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Fri, Nov 19, 2010 at 10:48 AM, Robert O'Callahan rob...@ocallahan.orgwrote: On Fri, Nov 19, 2010 at 10:46 AM, Darin Fisher da...@chromium.org wrote: I agree. What's the use case for animating hidden tabs (or canvases that are hidden)? One of the big problems with JavaScript based animations is that they have no way of knowing they should go idle when their window is hidden (in a background tab or otherwise). The same API used to rate-limit rendering could address the problem of hidden tabs too. Yes. As I mentioned, we do that in Firefox. Please read what I wrote above. Hmm, maybe I didn't mention it in this thread yet, sorry. I did mention the reason we want to guarantee the callback eventually fires: apps often want to do something when an animation ends. Having to write a special code path specifically to handle the case where an animation ends but the tab/element is hidden sounds to me like it's going to be error-prone. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Thu, Nov 18, 2010 at 1:54 PM, Robert O'Callahan rob...@ocallahan.orgwrote: On Fri, Nov 19, 2010 at 10:48 AM, Robert O'Callahan rob...@ocallahan.orgwrote: On Fri, Nov 19, 2010 at 10:46 AM, Darin Fisher da...@chromium.orgwrote: I agree. What's the use case for animating hidden tabs (or canvases that are hidden)? One of the big problems with JavaScript based animations is that they have no way of knowing they should go idle when their window is hidden (in a background tab or otherwise). The same API used to rate-limit rendering could address the problem of hidden tabs too. Yes. As I mentioned, we do that in Firefox. Please read what I wrote above. Hmm, maybe I didn't mention it in this thread yet, sorry. I did mention the reason we want to guarantee the callback eventually fires: apps often want to do something when an animation ends. Having to write a special code path specifically to handle the case where an animation ends but the tab/element is hidden sounds to me like it's going to be error-prone. I totally see that some bad code could be error prone if we don't guarantee the callback is eventually fired. On the other hand, guaranteeing it gets fired even if it's offscreen seems to have all the other repercussions (excess cpu usage, excess memory paging), those both could lead to a bad browsing experience. It seems like guaranteeing animationFrame callbacks get called even when offscreen is helping bad programmers (their incorrect code works) where as never calling them when offscreen is helping users (their browser is more likely to be responsive). Is there some way to solve both issues? Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Fri, Nov 19, 2010 at 11:32 AM, Gregg Tavares (wrk) g...@google.comwrote: I totally see that some bad code could be error prone if we don't guarantee the callback is eventually fired. On the other hand, guaranteeing it gets fired even if it's offscreen seems to have all the other repercussions (excess cpu usage, excess memory paging), those both could lead to a bad browsing experience. It seems like guaranteeing animationFrame callbacks get called even when offscreen is helping bad programmers (their incorrect code works) where as never calling them when offscreen is helping users (their browser is more likely to be responsive). Is there some way to solve both issues? Helping bad programmers is not a bad thing. Helping bad programmers helps users, because they are less likely to encounter bugs. Given that millions of Web applications use constant setTimeouts today, and will continue to do so no matter what we do, I think rather than trying to make requestAnimationFrame more efficient at the expense of making it error-prone, it would be better for implementors to come up with more general solutions to the busy background tab problem. For example, a browser could force the HTML5 event loop for a background tab to sleep for arbitrary periods of time. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
I suppose we could have a variant API that explicitly means I don't care if the callback never gets called. I don't know what to call it, though. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Tue, Nov 16, 2010 at 12:28 PM, Robert O'Callahan rob...@ocallahan.orgwrote: On Wed, Nov 17, 2010 at 7:52 AM, Gregg Tavares (wrk) g...@google.comwrote: So if the JS on the beforePaint takes a while to complete what happens to the browser? For example if you are resizing the browser? Is the browser forced not to be able to actually paint until JS returns? Not necessarily. In Firefox 4, yes. In Mobile Firefox, which supports compositing in a separate process from the content, no. Now, when animation is happening on a separate compositor thread that guarantee has to be relaxed a bit. But we'll still try to meet it on a best-effort basis --- i.e. we'll run the JS animations once per composited frame, if the JS can keep up. So you're saying that there's no guarantee that requestAnimationFrame will actually keep things in sync? Right. A cast-iron guarantee that requestAnimationFrame callbacks will run to completion before painting is incompatible with the goal of being able to repaint the browser window even if scripts are running too long or completely hung. But we *can* guarantee that a) scripted animations stay in sync with each other, and b) if the HTML5 event loop is not too busy (e.g., animation scripts take much less time to complete than the interval between composited frames and the content process is otherwise idle), scripted animations will stay in sync with with declarative animations even if the declarative animations are being processed by an off-main-thread compositing framework. (OK, this is a bit speculative since we haven't implemented it yet, but the approach seems straightforward.) Just blue skying here but It seems like if your goal is to keep animations in sync the trigger should be an animation tick, not a repaint. In otherwords, you want to give JS a chance to update stuff anytime a CSS animation updates stuff. That would separate the issue from painting. So what about an onAnimation type of event? That would separate this issue of the browser having to wait for JS during a paint and still keep things in sync. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Wed, Nov 17, 2010 at 10:45 AM, Gregg Tavares (wrk) g...@google.comwrote: On Tue, Nov 16, 2010 at 12:28 PM, Robert O'Callahan rob...@ocallahan.orgwrote: On Wed, Nov 17, 2010 at 7:52 AM, Gregg Tavares (wrk) g...@google.comwrote: So if the JS on the beforePaint takes a while to complete what happens to the browser? For example if you are resizing the browser? Is the browser forced not to be able to actually paint until JS returns? Not necessarily. In Firefox 4, yes. In Mobile Firefox, which supports compositing in a separate process from the content, no. Now, when animation is happening on a separate compositor thread that guarantee has to be relaxed a bit. But we'll still try to meet it on a best-effort basis --- i.e. we'll run the JS animations once per composited frame, if the JS can keep up. So you're saying that there's no guarantee that requestAnimationFrame will actually keep things in sync? Right. A cast-iron guarantee that requestAnimationFrame callbacks will run to completion before painting is incompatible with the goal of being able to repaint the browser window even if scripts are running too long or completely hung. But we *can* guarantee that a) scripted animations stay in sync with each other, and b) if the HTML5 event loop is not too busy (e.g., animation scripts take much less time to complete than the interval between composited frames and the content process is otherwise idle), scripted animations will stay in sync with with declarative animations even if the declarative animations are being processed by an off-main-thread compositing framework. (OK, this is a bit speculative since we haven't implemented it yet, but the approach seems straightforward.) Just blue skying here but It seems like if your goal is to keep animations in sync the trigger should be an animation tick, not a repaint. In otherwords, you want to give JS a chance to update stuff anytime a CSS animation updates stuff. That would separate the issue from painting. So what about an onAnimation type of event? That would separate this issue of the browser having to wait for JS during a paint and still keep things in sync. Think about this some more. the point if the previous suggestion is that updating keeping a JS animation in sync with a CSS animation has nothing to do with painting or rendering. The fact that apparently firefox ties those 2 things together is an artifact of firefox's implementation. It's just has valid to for example have animation running on 1 thread and rendering on another. Many console/pc games do this. To keep animations in sync requires syncing the animation values in the animation thread, not deciding to update values during rendering. So, if the goal is to let JS sync with CSS animations, putting the in events related to painting is the wrong model. Solving that problem particular goal it would make more sense to add a cssAnimationTick event or something. Any JS that wants to say in sync would add an event handler window.addEventHandler('animationTick, updateAnimations, ...); The handler would get passed a clock similar to how beforePaint works now. Of course going down that path doesn't solve the issue I'm trying to solve which could be stated as *) Don't render from JS unless visible (ie, don't execute expensive 2d or 3d canvas rendering calls when not visible) With the caveats of a) Make it extremely easy to do the right thing so that few if any sites making canvas ads or canvas games hog the CPU when not visible. b) don't make the browser wait on JavaScript. c) don't render more than needed. (ie, don't render 60 frames a second if you're only changing stuff at 15) It seems like a 'element.setRenderCallback(func, time)' which works exactly the same as setInterval but only when that element is visible would solve both of those issues. If you don't want it on element then make it window.setRenderCallback(element, func, time). The problem with a name like setRenderCallback is it seems like it's tied to rendering which is what I want to avoid which is why setIntervalIfVisible makes more sense. That name does not imply it has anything to do with rendering. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Thu, Nov 18, 2010 at 11:30 AM, Cameron McCormack c...@mcc.id.au wrote: Incidentally, I wonder if the beforepaint/animationTick event could be dropped altogether. Why isn’t just the callback sufficient? For animation, it is sufficient. We should drop the beforePaint event from the spec for now. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Thu, Nov 18, 2010 at 11:22 AM, Gregg Tavares (wrk) g...@google.comwrote: Think about this some more. the point if the previous suggestion is that updating keeping a JS animation in sync with a CSS animation has nothing to do with painting or rendering. The fact that apparently firefox ties those 2 things together is an artifact of firefox's implementation. It's just has valid to for example have animation running on 1 thread and rendering on another. Many console/pc games do this. To keep animations in sync requires syncing the animation values in the animation thread, not deciding to update values during rendering. But for maximum smoothness you want to update your animation once per painted frame. It doesn't matter how many threads you use and whether you do it during rendering. So, if the goal is to let JS sync with CSS animations, putting the in events related to painting is the wrong model. Solving that problem particular goal it would make more sense to add a cssAnimationTick event or something. Any JS that wants to say in sync would add an event handler window.addEventHandler('animationTick, updateAnimations, ...); The handler would get passed a clock similar to how beforePaint works now. Let's not get hung up on the beforePaint name. As Cameron mentioned, we should probably just ditch the event from the proposal altogether. Of course going down that path doesn't solve the issue I'm trying to solve which could be stated as *) Don't render from JS unless visible (ie, don't execute expensive 2d or 3d canvas rendering calls when not visible) With the caveats of a) Make it extremely easy to do the right thing so that few if any sites making canvas ads or canvas games hog the CPU when not visible. b) don't make the browser wait on JavaScript. c) don't render more than needed. (ie, don't render 60 frames a second if you're only changing stuff at 15) Those are good goals, except I think we need to drill down into (c). Are people changing stuff at 15Hz for crude performance tuning, or for some other reason? Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On 11/17/10 5:22 PM, Gregg Tavares (wrk) wrote: Think about this some more. the point if the previous suggestion is that updating keeping a JS animation in sync with a CSS animation has nothing to do with painting or rendering. The fact that apparently firefox ties those 2 things together is an artifact of firefox's implementation. Oh, I see the issue. The event name. The name was just picked as a way of telling script authors something about what the callback means All that Gecko promises right now is that you get the callback, then SMIL and Transitions and any pending style changes (including the ones your just caused) are processed and the layout/style of the page updated. Painting is in fact completely decoupled from this process in Gecko at the moment, except insofar as they happen on the same thread. Nothing guarantees that you won't get another MozBeforePaint event before painting actually happens, or that you won't get multiple paints in a row without a MozBeforePaint event in between. So yeah, the event name is somewhat suboptimal. ;) Again, all the event means is we're about to resample declarative animations; this is your chance to do script stuff that's supposed to look like an animation. -Boris
Re: requestAnimationFrame
On Wed, Nov 17, 2010 at 6:27 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 11/17/10 5:22 PM, Gregg Tavares (wrk) wrote: Think about this some more. the point if the previous suggestion is that updating keeping a JS animation in sync with a CSS animation has nothing to do with painting or rendering. The fact that apparently firefox ties those 2 things together is an artifact of firefox's implementation. Oh, I see the issue. The event name. The name was just picked as a way of telling script authors something about what the callback means All that Gecko promises right now is that you get the callback, then SMIL and Transitions and any pending style changes (including the ones your just caused) are processed and the layout/style of the page updated. Painting is in fact completely decoupled from this process in Gecko at the moment, except insofar as they happen on the same thread. Nothing guarantees that you won't get another MozBeforePaint event before painting actually happens, or that you won't get multiple paints in a row without a MozBeforePaint event in between. So yeah, the event name is somewhat suboptimal. ;) Again, all the event means is we're about to resample declarative animations; this is your chance to do script stuff that's supposed to look like an animation. In Safari (and at some point in Chrome as well) declarative animations are not necessarily sampled in the main thread. In fact, during an animation the main thread could be completely idle or completely busy running some piece of long-running javascript. If the computed styles on an animating element are queried a value is interpolated from the main thread independently of the animation itself. It wouldn't be possible to fire an event like this without adding additional synchronization between the two threads which would make the animation less smooth. I'm not entirely convinced about how important it is to synchronize declarative and script-driven animations versus making declarative animations work really well. - James -Boris
Re: requestAnimationFrame
On Wed, Nov 17, 2010 at 5:20 PM, Robert O'Callahan rob...@ocallahan.orgwrote: On Thu, Nov 18, 2010 at 11:22 AM, Gregg Tavares (wrk) g...@google.comwrote: Think about this some more. the point if the previous suggestion is that updating keeping a JS animation in sync with a CSS animation has nothing to do with painting or rendering. The fact that apparently firefox ties those 2 things together is an artifact of firefox's implementation. It's just has valid to for example have animation running on 1 thread and rendering on another. Many console/pc games do this. To keep animations in sync requires syncing the animation values in the animation thread, not deciding to update values during rendering. But for maximum smoothness you want to update your animation once per painted frame. It doesn't matter how many threads you use and whether you do it during rendering. So, if the goal is to let JS sync with CSS animations, putting the in events related to painting is the wrong model. Solving that problem particular goal it would make more sense to add a cssAnimationTick event or something. Any JS that wants to say in sync would add an event handler window.addEventHandler('animationTick, updateAnimations, ...); The handler would get passed a clock similar to how beforePaint works now. Let's not get hung up on the beforePaint name. As Cameron mentioned, we should probably just ditch the event from the proposal altogether. Of course going down that path doesn't solve the issue I'm trying to solve which could be stated as *) Don't render from JS unless visible (ie, don't execute expensive 2d or 3d canvas rendering calls when not visible) With the caveats of a) Make it extremely easy to do the right thing so that few if any sites making canvas ads or canvas games hog the CPU when not visible. b) don't make the browser wait on JavaScript. c) don't render more than needed. (ie, don't render 60 frames a second if you're only changing stuff at 15) Those are good goals, except I think we need to drill down into (c). Are people changing stuff at 15Hz for crude performance tuning, or for some other reason? Let's ignore (c) for the moment. I feel with (a) and (b) alone there are still issues to discuss. On (a) Take this page (http://boingboing.net) At the time I checked it today (6:55pm PST) it had 10 instances of flash running. O page load 3 were animating continuallty, 7 were idle. The 7 idle ones were all video with custom UIs. Of those 7, 6 of them will animate constantly once the video is finished advertising other videos to play. That means at any one time, if this was canvas based, 9 areas will be re-rendered by JavaScript on each animationFrame. It seems like giving the browser more info by tying these animation frames to specific elements would let the browser not call animationFrame callbacks unless the element it is tied to is on the screen and that would be a pretty good thing. If all 10 of those areas were re-rendering their ads all the time I suspect that page would get pretty slow, especially on netbooks. As it is, only 1-3 areas are ever visible at once. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On 11/17/10 9:48 PM, James Robinson wrote: In Safari (and at some point in Chrome as well) declarative animations are not necessarily sampled in the main thread. Right, that's the direction Robert mentioned Gecko is headed as well. I'm not entirely convinced about how important it is to synchronize declarative and script-driven animations I think it's pretty important to do something that makes it easy to at least try to synchronize them, unless you think declarative animations cover all use cases (they don't) or unless you want to force people to go all-script as soon as they have to script any one thing (undesirable). Robert has described how we see this working in Gecko, for what it's worth. -Boris
Re: requestAnimationFrame
On Mon, Nov 15, 2010 at 7:24 PM, Robert O'Callahan rob...@ocallahan.orgwrote: On Tue, Nov 16, 2010 at 1:45 PM, Gregg Tavares (wrk) g...@google.comwrote: On Mon, Nov 15, 2010 at 4:07 PM, Robert O'Callahan rob...@ocallahan.orgwrote: On Tue, Nov 16, 2010 at 12:55 PM, Gregg Tavares (wrk) g...@google.comwrote: I've seen proposals for something more like element.setInternvalIfVisible(func, internval); Which is the same as setInterval but only gets called if the element is visible. With that kind of API there is no connection to rendering. Each area that needs animation can set the framerate it is hoping to get. The UA can throttle if it wants to. What happens if one element's event handler makes another element visible, will the second element's timer be able to fire or not? Does it matter? Yes, I think it probably does matter for interop. What happens now? With mozRequestAnimationFrame, visibility is not relevant to whether the callbacks fire, so the question does not arise. Now, with setInterval there is no connection to rendering. I set the code to update one element to have an interval of 16 and another to have an interval of 100. If the first one makes the second one visible that doesn't effect whether or not the second one's set interval function gets called. If there was a setIntervalIfVisible and that behavior was browser independent how would that make things worse than they are today? It seem like if visible is just a hint to the browser that it doesn't need to call the interval function if it doesn't want to. It doesn't need to be a guaranteed that it will be called when visible any more than the current setInterval is a guarantee that it will be called at the interval rate. mozRequestAnimationFrame actually guarantees that you will be called when the browser paints. Otherwise we can't guarantee that JS animations will stay in sync with declarative animations. So if the JS on the beforePaint takes a while to complete what happens to the browser? For example if you are resizing the browser? Is the browser forced not to be able to actually paint until JS returns? Now, when animation is happening on a separate compositor thread that guarantee has to be relaxed a bit. But we'll still try to meet it on a best-effort basis --- i.e. we'll run the JS animations once per composited frame, if the JS can keep up. So you're saying that there's no guarantee that requestAnimationFrame will actually keep things in sync? When an element becomes visible, does its timer fire immediately if the last firing was more than 'interval' ago? Yes? No? Does it matter? What happens now? I suspect it would matter for interop, yes. Again, with requestAnimationFrame the question does not arise. I'm not trying to be argumentative. I'm just not seeing the issue. Certainly I'd like various areas to be updated together, or in sync, or when visible but that seems like it could be up the UA. If one UA has a simple implementation and another UA as more complex one that gives a better user experience then that's reason to switch to that browser. As Boris mentioned, keeping multiple animations (including declarative animations) in sync was a design goal for requestAnimationFrame. This seems like you'd just pass in 0 for the interval. The UA can decide whether or not to call you as fast as it can or at 60hz or whatever it things is appropriate just as it does for setInterval today. OK. To summarize, I think you have raised two separate feature requests here: 1) Provide an API that lets authors specify a maximum frame rate 2) Provide an API that lets authors avoid getting a callback while a particular element is invisible I'm curious about the use-cases that require #1, and given it can be implemented on top of requestAnimationFrame, the question for any proposal is whether the extra convenience justifies the surface area. (And note that even something like setInternvalIfVisible requires some lines of code for the animation script to figure out which frame it should display.) I'm not sure how important #2 is. If your callback includes if (element.getBoundingClientRect().top window.innerHeight) return;, I think you'd be pretty close to the same effect. But if you have a lot of animated elements, most of which are not visible, I can see that native support could be helpful. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Tue, Nov 16, 2010 at 10:52 AM, Gregg Tavares (wrk) g...@google.com wrote: On Mon, Nov 15, 2010 at 7:24 PM, Robert O'Callahan rob...@ocallahan.org wrote: Now, when animation is happening on a separate compositor thread that guarantee has to be relaxed a bit. But we'll still try to meet it on a best-effort basis --- i.e. we'll run the JS animations once per composited frame, if the JS can keep up. So you're saying that there's no guarantee that requestAnimationFrame will actually keep things in sync? Right; if the browser is trying to paint animation frames every 20ms, and two functions have both registered themselves for the next frame, but the first function takes 50ms to run, then of course the second one won't get to run at the same time. It'll be delayed until the 3rd frame after or so. ~TJ
Re: requestAnimationFrame
On 11/16/10 1:52 PM, Gregg Tavares (wrk) wrote: So if the JS on the beforePaint takes a while to complete what happens to the browser? For example if you are resizing the browser? Is the browser forced not to be able to actually paint until JS returns? I'll let roc talk about how he sees this working in the future, and in particular about your compositor thread question below, but in the current Gecko model, this is correct. The content area will not paint updates, change layout, etc, until the JS returns. Note that in your resize scenario I would in fact not expect the layout to change under a script while the script is running, so the browser couldn't relayout to the new size until the JS returns anyway. Now, when animation is happening on a separate compositor thread that guarantee has to be relaxed a bit. But we'll still try to meet it on a best-effort basis --- i.e. we'll run the JS animations once per composited frame, if the JS can keep up. So you're saying that there's no guarantee that requestAnimationFrame will actually keep things in sync? The guarantees we currently supply are: 1) Your requestAnimationFrame handler will be called before painting. 2) The handler is passed an argument (directly, if you used a function callback; as event.timeStamp if you used an event handler) that indicates the time that was or will be used to sample SMIL animations and CSS Transitions that will paint when the paint happens. This may be different from the current time, depending on what other animation frame handlers are involved and how long they take. Now your script knows the time that it's painting at wrt animations, and can compute the proper thing to be showing to be in sync with them. -Boris
Re: requestAnimationFrame
On Wed, Nov 17, 2010 at 7:52 AM, Gregg Tavares (wrk) g...@google.comwrote: So if the JS on the beforePaint takes a while to complete what happens to the browser? For example if you are resizing the browser? Is the browser forced not to be able to actually paint until JS returns? Not necessarily. In Firefox 4, yes. In Mobile Firefox, which supports compositing in a separate process from the content, no. Now, when animation is happening on a separate compositor thread that guarantee has to be relaxed a bit. But we'll still try to meet it on a best-effort basis --- i.e. we'll run the JS animations once per composited frame, if the JS can keep up. So you're saying that there's no guarantee that requestAnimationFrame will actually keep things in sync? Right. A cast-iron guarantee that requestAnimationFrame callbacks will run to completion before painting is incompatible with the goal of being able to repaint the browser window even if scripts are running too long or completely hung. But we *can* guarantee that a) scripted animations stay in sync with each other, and b) if the HTML5 event loop is not too busy (e.g., animation scripts take much less time to complete than the interval between composited frames and the content process is otherwise idle), scripted animations will stay in sync with with declarative animations even if the declarative animations are being processed by an off-main-thread compositing framework. (OK, this is a bit speculative since we haven't implemented it yet, but the approach seems straightforward.) Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
requestAnimationFrame
following in the footsteps of a previous thread http://lists.w3.org/Archives/Public/public-webapps/2009OctDec/0223.html I'd like to see if there is some consensus on this issue. Various people are anxious to see this happen in more browsers. A couple of questions came up for requestAnimationFrame (see http://weblogs.mozillazine.org/roc/archives/2010/08/mozrequestanima.html) One is, how should this api be used if I want an app to update at 10hz. It seems to be designed to assume I want the maximum frame rate. If I want to run slower would I just use setInterval(function() { window.requestAnimationFrame(); }, 100); // request frames at 10hz? That's fine if that's the answer But that brings up the next question. I'm in some alternate world where there is no Flash, instead all ads are implemented in Canvas. Therefore a site like cnn.com or msnbc.com has 5 canvases running ads in each one. I don't really want all 5 canvases redrawn if they are not on the screen but the current design has requestAnimationFrame and beforePaint to be window level apis. That seems to have 2 issues. 1) All of them will get a beforePaint event even if most or all of them are scrolled off the visible area since there is only 1 beforePaint event attached to the window. 2) All of them will get beforePaint events at the speed of the fastest one. If one ad only needs to update at 5hz and other updates at 60hz both will update at 60hz. Do those issues matter? If they do matter would making both requestAnimationFrame and beforePaint be element level APIs solve it?
Re: requestAnimationFrame
On 11/15/10 6:03 PM, Gregg Tavares (wrk) wrote: One is, how should this api be used if I want an app to update at 10hz. It seems to be designed to assume I want the maximum frame rate. The initial API was designed to replace setTimeout(..., 0) animations, yeah. The idea was to ask for animate as smoothly as possible but allow the browser to choose the actual animation rate. setInterval(function() { window.requestAnimationFrame(); }, 100); // request frames at 10hz? This seems like it would work, yes It may be suboptimal if you have multiple consumers, because you end up with multiple timers in flight. But you'd get that anyway if you had some consumers wanting 10Hz and some wanting 11Hz and some wanting 9Hz It's worth thinking about this a bit, but I'm not sure there's a great solution here. But that brings up the next question. I'm in some alternate world where there is no Flash, instead all ads are implemented in Canvas. Therefore a site like cnn.com http://cnn.com or msnbc.com http://msnbc.com has 5 canvases running ads in each one. I don't really want all 5 canvases redrawn if they are not on the screen but the current design has requestAnimationFrame and beforePaint to be window level apis. Note that the beforePaint event can make arbitrary changes to the DOM (and in particular can change whether things are visible)... 1) All of them will get a beforePaint event even if most or all of them are scrolled off the visible area since there is only 1 beforePaint event attached to the window. 2) All of them will get beforePaint events at the speed of the fastest one. If one ad only needs to update at 5hz and other updates at 60hz both will update at 60hz. Do those issues matter? If they do matter would making both requestAnimationFrame and beforePaint be element level APIs solve it? The current mozRequestAnimationFrame implementation allows passing a function. If no function is passed, an event is fired at the window. If a function is passed, that function is called. So in this case, each canvas could pass a separate function that just modifies that canvas. If they want to throttle themselves they'd use your setInterval suggestion above as needed. That would address #2 above. I suppose we could do something similar with events and event handlers if people think it's a better API. For #1, things are more difficult; a lot of the work you have to do to determine whether something is inside the visible area is work you want to put off until _after_ all the beforePaint handlers have run. -Boris
Re: requestAnimationFrame
On Mon, Nov 15, 2010 at 3:28 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 11/15/10 6:03 PM, Gregg Tavares (wrk) wrote: One is, how should this api be used if I want an app to update at 10hz. It seems to be designed to assume I want the maximum frame rate. The initial API was designed to replace setTimeout(..., 0) animations, yeah. The idea was to ask for animate as smoothly as possible but allow the browser to choose the actual animation rate. setInterval(function() { window.requestAnimationFrame(); }, 100); // request frames at 10hz? This seems like it would work, yes It may be suboptimal if you have multiple consumers, because you end up with multiple timers in flight. But you'd get that anyway if you had some consumers wanting 10Hz and some wanting 11Hz and some wanting 9Hz It's worth thinking about this a bit, but I'm not sure there's a great solution here. But that brings up the next question. I'm in some alternate world where there is no Flash, instead all ads are implemented in Canvas. Therefore a site like cnn.com http://cnn.com or msnbc.com http://msnbc.com has 5 canvases running ads in each one. I don't really want all 5 canvases redrawn if they are not on the screen but the current design has requestAnimationFrame and beforePaint to be window level apis. Note that the beforePaint event can make arbitrary changes to the DOM (and in particular can change whether things are visible)... 1) All of them will get a beforePaint event even if most or all of them are scrolled off the visible area since there is only 1 beforePaint event attached to the window. 2) All of them will get beforePaint events at the speed of the fastest one. If one ad only needs to update at 5hz and other updates at 60hz both will update at 60hz. Do those issues matter? If they do matter would making both requestAnimationFrame and beforePaint be element level APIs solve it? The current mozRequestAnimationFrame implementation allows passing a function. If no function is passed, an event is fired at the window. If a function is passed, that function is called. So in this case, each canvas could pass a separate function that just modifies that canvas. If they want to throttle themselves they'd use your setInterval suggestion above as needed. That would address #2 above. How would setInterval with multiple functions on mozRequestAnimationFrame solve this issue? They are still all going to get called at the fastest interval right? Or did you mean if mozRequestAnimationFrame was moved to an element level function? I suppose we could do something similar with events and event handlers if people think it's a better API. For #1, things are more difficult; a lot of the work you have to do to determine whether something is inside the visible area is work you want to put off until _after_ all the beforePaint handlers have run. I've seen proposals for something more like element.setInternvalIfVisible(func, internval); Which is the same as setInterval but only gets called if the element is visible. With that kind of API there is no connection to rendering. Each area that needs animation can set the framerate it is hoping to get. The UA can throttle if it wants to. Would something more like that solve the issue? -Boris
Re: requestAnimationFrame
On Tue, Nov 16, 2010 at 12:03 PM, Gregg Tavares (wrk) g...@google.comwrote: One is, how should this api be used if I want an app to update at 10hz. It seems to be designed to assume I want the maximum frame rate. If I want to run slower would I just use setInterval(function() { window.requestAnimationFrame(); }, 100); // request frames at 10hz? That's fine if that's the answer If you really want to animate in 10Hz steps, then I suggest you do something like var start = window.animationTime; var rate = 10; // Hz var duration = 10; // s var lastFrameNumber; function animate() { var elapsed = window.animationTime - start; if (elapsed duration) { window.requestAnimationFrame(animate); } var frameNumber = Math.round(elapsed/(1000/rate)); if (frameNumber == lastFrameNumber) return; lastFrameNumber = frameNumber; // ... update the display based on frameNumber ... } window.requestAnimationFrame(animate); (Out of curiosity, what are the use-cases for this?) That seems to have 2 issues. 1) All of them will get a beforePaint event even if most or all of them are scrolled off the visible area since there is only 1 beforePaint event attached to the window. Something could be done here, but it seems rather complex to specify things in a way that avoids firing callbacks when relevant content is out of view. 2) All of them will get beforePaint events at the speed of the fastest one. If one ad only needs to update at 5hz and other updates at 60hz both will update at 60hz. The above approach solves this I think. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Tue, Nov 16, 2010 at 12:55 PM, Gregg Tavares (wrk) g...@google.comwrote: I've seen proposals for something more like element.setInternvalIfVisible(func, internval); Which is the same as setInterval but only gets called if the element is visible. With that kind of API there is no connection to rendering. Each area that needs animation can set the framerate it is hoping to get. The UA can throttle if it wants to. What happens if one element's event handler makes another element visible, will the second element's timer be able to fire or not? When an element becomes visible, does its timer fire immediately if the last firing was more than 'interval' ago? If the author just wants a smooth animation, what should they pass as the interval? For smooth animations, it seems to me that the browser alone should choose the frame rate. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Mon, Nov 15, 2010 at 3:58 PM, Robert O'Callahan rob...@ocallahan.org wrote: On Tue, Nov 16, 2010 at 12:03 PM, Gregg Tavares (wrk) g...@google.com wrote: One is, how should this api be used if I want an app to update at 10hz. It seems to be designed to assume I want the maximum frame rate. If I want to run slower would I just use setInterval(function() { window.requestAnimationFrame(); }, 100); // request frames at 10hz? That's fine if that's the answer If you really want to animate in 10Hz steps, then I suggest you do something like var start = window.animationTime; var rate = 10; // Hz var duration = 10; // s var lastFrameNumber; function animate() { var elapsed = window.animationTime - start; if (elapsed duration) { window.requestAnimationFrame(animate); } var frameNumber = Math.round(elapsed/(1000/rate)); if (frameNumber == lastFrameNumber) return; lastFrameNumber = frameNumber; // ... update the display based on frameNumber ... } window.requestAnimationFrame(animate); (Out of curiosity, what are the use-cases for this?) *If* this is a use case that is important enough to solve, then one solution would be to allow a interval to be passed to requestAnimationFrame when a callback is specified. When such an interval is passed, the implementation would call the callback no sooner than the requested interval. Though one concern would be that people might depend on the callback being called exactly then, and not take into account the fact that the callback rate might be significantly slower if for example the page is in a background tab. / Jonas
Re: requestAnimationFrame
On Mon, Nov 15, 2010 at 3:58 PM, Robert O'Callahan rob...@ocallahan.orgwrote: On Tue, Nov 16, 2010 at 12:03 PM, Gregg Tavares (wrk) g...@google.comwrote: One is, how should this api be used if I want an app to update at 10hz. It seems to be designed to assume I want the maximum frame rate. If I want to run slower would I just use setInterval(function() { window.requestAnimationFrame(); }, 100); // request frames at 10hz? That's fine if that's the answer If you really want to animate in 10Hz steps, then I suggest you do something like var start = window.animationTime; var rate = 10; // Hz var duration = 10; // s var lastFrameNumber; function animate() { var elapsed = window.animationTime - start; if (elapsed duration) { window.requestAnimationFrame(animate); } var frameNumber = Math.round(elapsed/(1000/rate)); if (frameNumber == lastFrameNumber) return; lastFrameNumber = frameNumber; // ... update the display based on frameNumber ... } window.requestAnimationFrame(animate); That seems quite a bit more complicated than setInterval(myRenderFunction, 100); Which is what you'd do today. (Out of curiosity, what are the use-cases for this?) There is plenty of flash content that has a lower than 60hz (or fast as possible) refresh rate. When something is instead implementing in HTML5 instead of Flash what should they do to get the similar results? Checking cnn.com, time.com, arstechnica.com, wired.com and msnbc.com I found that 7 ads were set to run at 18hz, 3 were set to run at 24hz, 2 were set to run at 30hz. I used SWF Infohttps://addons.mozilla.org/en-US/firefox/addon/45361/to check the fps setting. I have no idea why they don't choose run as fast as possible. I could be laziness, it could be that it makes the pages too slow and unresponsive to set them to as fast as possible, it could be that rendering 3 times more then necessary, 60hz vs 18hz would eat battery life, it could be an artistic choice, it could be just that flash makes you pick one vs defaulting to fast as possible. That seems to have 2 issues. 1) All of them will get a beforePaint event even if most or all of them are scrolled off the visible area since there is only 1 beforePaint event attached to the window. Something could be done here, but it seems rather complex to specify things in a way that avoids firing callbacks when relevant content is out of view. 2) All of them will get beforePaint events at the speed of the fastest one. If one ad only needs to update at 5hz and other updates at 60hz both will update at 60hz. The above approach solves this I think. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Mon, Nov 15, 2010 at 4:07 PM, Robert O'Callahan rob...@ocallahan.orgwrote: On Tue, Nov 16, 2010 at 12:55 PM, Gregg Tavares (wrk) g...@google.comwrote: I've seen proposals for something more like element.setInternvalIfVisible(func, internval); Which is the same as setInterval but only gets called if the element is visible. With that kind of API there is no connection to rendering. Each area that needs animation can set the framerate it is hoping to get. The UA can throttle if it wants to. What happens if one element's event handler makes another element visible, will the second element's timer be able to fire or not? Does it matter? What happens now? Now, with setInterval there is no connection to rendering. I set the code to update one element to have an interval of 16 and another to have an interval of 100. If the first one makes the second one visible that doesn't effect whether or not the second one's set interval function gets called. If there was a setIntervalIfVisible and that behavior was browser independent how would that make things worse than they are today? It seem like if visible is just a hint to the browser that it doesn't need to call the interval function if it doesn't want to. It doesn't need to be a guaranteed that it will be called when visible any more than the current setInterval is a guarantee that it will be called at the interval rate. When an element becomes visible, does its timer fire immediately if the last firing was more than 'interval' ago? Yes? No? Does it matter? What happens now? I'm not trying to be argumentative. I'm just not seeing the issue. Certainly I'd like various areas to be updated together, or in sync, or when visible but that seems like it could be up the UA. If one UA has a simple implementation and another UA as more complex one that gives a better user experience then that's reason to switch to that browser. If the author just wants a smooth animation, what should they pass as the interval? For smooth animations, it seems to me that the browser alone should choose the frame rate. This seems like you'd just pass in 0 for the interval. The UA can decide whether or not to call you as fast as it can or at 60hz or whatever it things is appropriate just as it does for setInterval today. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Mon, Nov 15, 2010 at 5:01 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote: * Gregg Tavares (wrk) wrote: There is plenty of flash content that has a lower than 60hz (or fast as possible) refresh rate. When something is instead implementing in HTML5 instead of Flash what should they do to get the similar results? Checking cnn.com, time.com, arstechnica.com, wired.com and msnbc.com I found that 7 ads were set to run at 18hz, 3 were set to run at 24hz, 2 were set to run at 30hz. I used SWF Infohttps://addons.mozilla.org/en-US/firefox/addon/45361/to check the fps setting. I have no idea why they don't choose run as fast as possible. I could be laziness, it could be that it makes the pages too slow and unresponsive to set them to as fast as possible, it could be that rendering 3 times more then necessary, 60hz vs 18hz would eat battery life, it could be an artistic choice, it could be just that flash makes you pick one vs defaulting to fast as possible. The frame rate is a number in the swf header that cannot be set to a as fast as possible value. Ah, so that also means that different animations can't run with different frame rates? Maybe having a global property which defines the maximum frame rate for all animations on the page would be enough then? Though it'll give ads and their embedders a fun property to fight over. / Jonas
Re: requestAnimationFrame
On Mon, Nov 15, 2010 at 5:10 PM, Jonas Sicking jo...@sicking.cc wrote: On Mon, Nov 15, 2010 at 5:01 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote: * Gregg Tavares (wrk) wrote: There is plenty of flash content that has a lower than 60hz (or fast as possible) refresh rate. When something is instead implementing in HTML5 instead of Flash what should they do to get the similar results? Checking cnn.com, time.com, arstechnica.com, wired.com and msnbc.com I found that 7 ads were set to run at 18hz, 3 were set to run at 24hz, 2 were set to run at 30hz. I used SWF Infohttps://addons.mozilla.org/en-US/firefox/addon/45361/to check the fps setting. I have no idea why they don't choose run as fast as possible. I could be laziness, it could be that it makes the pages too slow and unresponsive to set them to as fast as possible, it could be that rendering 3 times more then necessary, 60hz vs 18hz would eat battery life, it could be an artistic choice, it could be just that flash makes you pick one vs defaulting to fast as possible. The frame rate is a number in the swf header that cannot be set to a as fast as possible value. How does that info help resolve this? fast as possible effectively is that same as 60hz for all practical purposes and yet lots of people are not setting their flash animations to 60hz. Ah, so that also means that different animations can't run with different frame rates? Yes they can. One instance of flash is set to 18hz, another is set to 24hz, both are on the same page. Or are we talking about something else? Maybe having a global property which defines the maximum frame rate for all animations on the page would be enough then? Though it'll give ads and their embedders a fun property to fight over. / Jonas
Re: requestAnimationFrame
* Jonas Sicking wrote: On Mon, Nov 15, 2010 at 5:01 PM, Bjoern Hoehrmann derhoe...@gmx.net wrote: The frame rate is a number in the swf header that cannot be set to a as fast as possible value. Ah, so that also means that different animations can't run with different frame rates? That's the basic model and there are dependencies on that, for instance, you can ask the player to move to a specific frame, which would break if the frame rate changes unexpectedly. There may be ways to get a higher actual rate through forced redraws and by dynamically changing the rate, which more recent versions permit. -- Björn Höhrmann · mailto:bjo...@hoehrmann.de · http://bjoern.hoehrmann.de Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de 25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/
Re: requestAnimationFrame
On 11/15/10 6:55 PM, Gregg Tavares (wrk) wrote: How would setInterval with multiple functions on mozRequestAnimationFrame solve this issue? They are still all going to get called at the fastest interval right? Why? setInterval(function() { window.requestAnimationFrame(function redrawElem1() { /* ... */ }); }, 33); setInterval(function() { window.requestAnimationFrame(function redrawElem2() { /* ... */ }); }, 100); This should redraw elem1 close to 30Hz and elem2 close to 10Hz. Or did you mean if mozRequestAnimationFrame was moved to an element level function? The element involved can be encoded in the callback function passed to requestAnimationFrame, as above. I've seen proposals for something more like element.setInternvalIfVisible(func, internval); Which is the same as setInterval but only gets called if the element is visible. Right, but the point is that the work of determining whether things are visible is work you want to do _after_ animations have updated... With that kind of API there is no connection to rendering. I'm not sure what that means. Would something more like that solve the issue? Which issue are we trying to solve? The idea of the current animation frame API was to solve the following problems: 1) Provide a way to create smooth DOM animations that synchronize with SMIL and CSS3 Transitions. 2) Provide a way to throttle all such animations on the UA side (that includes throttling SMIL and Transitions). It sounds like you're trying to solve a somewhat different problem, right? -Boris
Re: requestAnimationFrame
On 11/15/10 7:45 PM, Gregg Tavares (wrk) wrote: Does it matter? What happens now? Now, with setInterval there is no connection to rendering. I set the code to update one element to have an interval of 16 and another to have an interval of 100. If the first one makes the second one visible that doesn't effect whether or not the second one's set interval function gets called. If there was a setIntervalIfVisible and that behavior was browser independent how would that make things worse than they are today? Well... we're trying to make things _better_, not no worse. I'm not trying to be argumentative. I'm just not seeing the issue. Certainly I'd like various areas to be updated together, or in sync Yes, that was one of the two main motivations for mozRequestAnimationFrame. Apart from the throttling (which is easy), this is by far the most important thing with the API. -Boris
Re: requestAnimationFrame
On Tue, Nov 16, 2010 at 1:26 PM, Gregg Tavares (wrk) g...@google.comwrote: On Mon, Nov 15, 2010 at 3:58 PM, Robert O'Callahan rob...@ocallahan.orgwrote: If you really want to animate in 10Hz steps, then I suggest you do something like var start = window.animationTime; var rate = 10; // Hz var duration = 10; // s var lastFrameNumber; function animate() { var elapsed = window.animationTime - start; if (elapsed duration) { window.requestAnimationFrame(animate); } var frameNumber = Math.round(elapsed/(1000/rate)); if (frameNumber == lastFrameNumber) return; lastFrameNumber = frameNumber; // ... update the display based on frameNumber ... } window.requestAnimationFrame(animate); That seems quite a bit more complicated than setInterval(myRenderFunction, 100); Which is what you'd do today. Sure, but a) it's easily implemented once as a ten-line function in a library and b) it's a lot more useful than setInterval ... for example it automatically skips frames as necessary. There is plenty of flash content that has a lower than 60hz (or fast as possible) refresh rate. When something is instead implementing in HTML5 instead of Flash what should they do to get the similar results? Checking cnn.com, time.com, arstechnica.com, wired.com and msnbc.com I found that 7 ads were set to run at 18hz, 3 were set to run at 24hz, 2 were set to run at 30hz. I used SWF Infohttps://addons.mozilla.org/en-US/firefox/addon/45361/to check the fps setting. I have no idea why they don't choose run as fast as possible. I could be laziness, it could be that it makes the pages too slow and unresponsive to set them to as fast as possible, it could be that rendering 3 times more then necessary, 60hz vs 18hz would eat battery life, it could be an artistic choice, it could be just that flash makes you pick one vs defaulting to fast as possible. OK, it would be useful to know the relative frequency of those reasons. Reasons of the form makes the page too slow/eats too much battery actually do not make compelling use-cases. Author-chosen frame rates for performance reasons are generally going to be wrong because the author doesn't know the capabilities of the client. Instead, the browser should be choosing the frame rate(s). IMHO the only feature we *might* want to add here is to allow authors to specify relative priorities somehow. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Tue, Nov 16, 2010 at 1:45 PM, Gregg Tavares (wrk) g...@google.comwrote: On Mon, Nov 15, 2010 at 4:07 PM, Robert O'Callahan rob...@ocallahan.orgwrote: On Tue, Nov 16, 2010 at 12:55 PM, Gregg Tavares (wrk) g...@google.comwrote: I've seen proposals for something more like element.setInternvalIfVisible(func, internval); Which is the same as setInterval but only gets called if the element is visible. With that kind of API there is no connection to rendering. Each area that needs animation can set the framerate it is hoping to get. The UA can throttle if it wants to. What happens if one element's event handler makes another element visible, will the second element's timer be able to fire or not? Does it matter? Yes, I think it probably does matter for interop. What happens now? With mozRequestAnimationFrame, visibility is not relevant to whether the callbacks fire, so the question does not arise. Now, with setInterval there is no connection to rendering. I set the code to update one element to have an interval of 16 and another to have an interval of 100. If the first one makes the second one visible that doesn't effect whether or not the second one's set interval function gets called. If there was a setIntervalIfVisible and that behavior was browser independent how would that make things worse than they are today? It seem like if visible is just a hint to the browser that it doesn't need to call the interval function if it doesn't want to. It doesn't need to be a guaranteed that it will be called when visible any more than the current setInterval is a guarantee that it will be called at the interval rate. mozRequestAnimationFrame actually guarantees that you will be called when the browser paints. Otherwise we can't guarantee that JS animations will stay in sync with declarative animations. Now, when animation is happening on a separate compositor thread that guarantee has to be relaxed a bit. But we'll still try to meet it on a best-effort basis --- i.e. we'll run the JS animations once per composited frame, if the JS can keep up. When an element becomes visible, does its timer fire immediately if the last firing was more than 'interval' ago? Yes? No? Does it matter? What happens now? I suspect it would matter for interop, yes. Again, with requestAnimationFrame the question does not arise. I'm not trying to be argumentative. I'm just not seeing the issue. Certainly I'd like various areas to be updated together, or in sync, or when visible but that seems like it could be up the UA. If one UA has a simple implementation and another UA as more complex one that gives a better user experience then that's reason to switch to that browser. As Boris mentioned, keeping multiple animations (including declarative animations) in sync was a design goal for requestAnimationFrame. This seems like you'd just pass in 0 for the interval. The UA can decide whether or not to call you as fast as it can or at 60hz or whatever it things is appropriate just as it does for setInterval today. OK. To summarize, I think you have raised two separate feature requests here: 1) Provide an API that lets authors specify a maximum frame rate 2) Provide an API that lets authors avoid getting a callback while a particular element is invisible I'm curious about the use-cases that require #1, and given it can be implemented on top of requestAnimationFrame, the question for any proposal is whether the extra convenience justifies the surface area. (And note that even something like setInternvalIfVisible requires some lines of code for the animation script to figure out which frame it should display.) I'm not sure how important #2 is. If your callback includes if (element.getBoundingClientRect().top window.innerHeight) return;, I think you'd be pretty close to the same effect. But if you have a lot of animated elements, most of which are not visible, I can see that native support could be helpful. Rob -- Now the Bereans were of more noble character than the Thessalonians, for they received the message with great eagerness and examined the Scriptures every day to see if what Paul said was true. [Acts 17:11]
Re: requestAnimationFrame
On Mon, Nov 15, 2010 at 6:17 PM, Boris Zbarsky bzbar...@mit.edu wrote: On 11/15/10 6:55 PM, Gregg Tavares (wrk) wrote: How would setInterval with multiple functions on mozRequestAnimationFrame solve this issue? They are still all going to get called at the fastest interval right? Why? setInterval(function() { window.requestAnimationFrame(function redrawElem1() { /* ... */ }); }, 33); setInterval(function() { window.requestAnimationFrame(function redrawElem2() { /* ... */ }); }, 100); My suggestion is that window.requestAnimationFrame(function redrawElem1() { ... }, 33); window.requestAnimationFrame(function redrawElem1() { ... }, 100); would be equivalent to the above (or rather, would be equivalent to using setTimeout). Though maybe limited-rate animations aren't common enough that the short-hand is needed. / Jonas