Use requestanimationframe to better implement JavaScript animation)

Source: Internet
Author: User
ArticleDirectory
    • Timer
    • Interval animation intervals
    • Problem
    • Mozrequestanimationframe
    • Webkitrequestanimationframe
    • Summary

For a long time, JavaScript animation is implemented by timer and interval. Although CSS transitions and animations are used to make it easier for Web developers to implement animations, the JavaScript-based animations have rarely changed over the years. It was not until the release of Firefox 4 that the first method to improve JavaScript animation was introduced. But we need to fully understand the improvements, which helps us understand how Web Animation evolves and improves.

Timer

The first mode used to create an animation is called using the setTimeout () chain. For a long period of time in Netscape 3's hayday, developers all remember a fixed latest market status bar that is everywhere on the network. It is usually similar to this:

(Function () {var MSG = "new advertisement", Len = 25, Pos = 0, padding = MSG. replace (/. /g ,""). substr (0, Len), finalmsg = Padding + MSG; function updatetext () {var curmsg = finalmsg. substr (Pos ++, Len); window. status = curmsg; If (Pos = finalmsg. length) {pos = 0;} setTimeout (updatetext, 100) ;}settimeout (updatetext, 100 );})();

If you want to test this section in your browserCodeYou can create a new <PRE> label to simulate window. status, for example, newsticker example.

This annoying web model was later hit by window. with the release of Explorer 4 and Netscape 4, the browser gives developers more control permissions on page elements for the first time. In this way, there is a new Animation Mode that uses JavaScript to dynamically change the element size, position, color, and so on. For example, the following is an animation that changes the DIV width to 100% (similar to the progress bar ):

(Function () {function updateprogress () {var DIV = document. getelementbyid ("status"); Div. style. width = (parseint (div. style. width, 10) + 5) + "%"; if (div. style. width! = "100%") {setTimeout (updateprogress, 100) ;}} setTimeout (updateprogress, 100 );})();

Although the animation on the page is different, the basic principle is the same: make a change, use setTimeout () interval to update the page, and then setTimeout to execute the next change, this process is executed repeatedly until the animation is completed (see progress bar animation). The early status bar animation technology is the same, but the animation is different.

Interval animation intervals

With the successful introduction of animations into the web, a new exploration begins. One animation is no longer enough. Now multiple animations are needed. The first attempt was to create multiple animation loops for each animation. It was a bit complicated to create multiple animations using setTimeout () in earlier browsers, so developers started to use setinterval () create a single animation loop to manage all the animations on the page, and a basic animation using wetinterval () is as follows:

 
(Function () {function updateanimations () {updatetext (); updateprogress ();} setinterval (updateanimations, 100 );})();

Create a small animation library. The updateanimations () method cyclically executes and changes each animation (with a news stock and progress bar running together. If no animation needs to be updated, this method can exit without doing anything, or even stop the animation loop until more animation updates are ready.

The tricky problem with animation is the latency. On the one hand, the interval must be short enough so that different animations can be smoothly carried out. On the other hand, it must be long enough so that the browser can complete rendering. The refresh frequency of most browsers is 60Hz, that is, 60 refresh times per second. Most browsers do not refresh more frequently than this because they know that end users cannot have a better experience.

In view of this, the optimal interval for smooth animation is 1000 ms/60, about 17 ms. At this frequency, you will see smooth animations, because you are most close to the frequency that the browser can achieve. Compared with previous animations, you will find that the animation at the 17ms interval is smoother and faster (because the animation updates are more frequent and no other modifications are made ), multiple animations may require throttling, so that the 17 Ms animation can be completed too quickly.

Problem

Even if the setinterval ()-based animation loop is more efficient than the setTimeout ()-based animation loop, there is still a problem. Neither setinterval () nor setTimeout () can be precise, this latency means that the second parameter you specify only indicates when the code will be added to the UI thread queue that may be executed by the browser. If there is other work in the queue before this, the code will not be executed until it is completed. In short, the latency in milliseconds does not indicate when the code will be executed, but when the code will be added to the queue. If the UI thread is busy or processing user actions, the code will not be executed immediately.

The key to a smooth animation is to understand when the next frame will be executed. Until now, there is no way to ensure that the next frame will be drawn in the browser. With the increasing popularity of <canvas> and the emergence of new browser-based games, developers are increasingly disappointed with the inaccuracy of setinterval () and setTimeout.

The browser's timer resolution increases this problem. The timer is not precise to milliseconds. Here are some common timer resolutions:

    • Internet Explorer 8 and earlier 15.625 Ms
    • Internet Explorer 9 and later 4 ms.
    • Firefox and Safari ~ 10 ms.
    • Chrome has a timer 4 ms.

IE versions earlier than version 9 have a resolution of 15.625, So 0 ~ Any value between 15 May be 0 or 15, but there is no difference. The timer resolution of ie9 is improved to 4 ms, but it is not specific when it involves animation. The timer resolution of Chrome is 4 ms, and that of Firefox and Safari is 10 ms. Therefore, even if you set the interval to the best display effect, you just get this approximate value.

Mozrequestanimationframe

Mozilla's Robert o'callahan was thinking about this and came up with a unique solution. He pointed out that the advantage of CSS transitions and animations is that the browser knows which animations will happen, so get the correct interval to refresh the UI. In JavaScript animation, the browser does not know that the animation is happening. His solution is to create a javasrequestanimationframe () method to tell the browser which JavaScript code is being executed, which optimizes browsing after executing some code.

The mozrequestanimationframe () method accepts a parameter and is a function called before screen re-painting. This function is used to generate the appropriate Dom style changes, which are used in the next re-painting. You can call javasrequestanimationframe () in the same way as calling setTimeout (). For example:

Function updateprogress () {var DIV = document. getelementbyid ("status"); Div. style. width = (parseint (div. style. width, 10) + 5) + "%"; if (div. style. left! = "100%") {required requestanimationframe (updateprogress) ;}} required requestanimationframe (updateprogress );

Because javasrequestanimationframe () only runs a given function once, you need to call it again in the next UI animation. You also need the same method to manage when to stop calling. Cool. It is a very smooth animation enhancement instance.

Therefore, javasrequestanimationframe () solves the problem that the browser does not know how many JavaScript animations are being executed and how many JavaScript animations are being executed. However, if you do not know when your code is actually executed, this solution also solves the problem.

The function passed to mozrequestanimationframe () is actually a time code for the next re-painting (measured in milliseconds from January 1, January 1, 1970 ). This is very important: mozrequestanimationframe () actually lists the vertices to be repainted and tells you the time they are in. In this way, you can decide how to better adjust your animation.

To obtain the time of the previous re-painting, you can query the mozanimationstarttime, which contains the time code of the previous re-painting. After the callback is passed, this value can be used to calculate the time used for the next screen re-painting. The typical mode of using these values is as follows:

Function draw (timestamp) {// calculate difference since last repaint var diff = timestamp-starttime; // use diff to determine correct next step // reset starttime to this repaint starttime = timestamp; // draw again implements requestanimationframe (draw);} var starttime = animated animationstarttime; required requestanimationframe (draw );

The key is that when the call is not called through callback for the first time, the mozanimationstarttime is the time that passes to the mozrequestanimationframe. In the callback function, the mozanimationstarttime is the average value of the Time Code passed in through the parameter.

Webkitrequestanimationframe

When many people are loyal to chrome, The webkitrequestanimationframe () method is created immediately. This version is slightly different from Firefox in two aspects. On the one hand, it does not pass the time code through the callback function, you will not be able to know when the next re-painting will happen, on the other hand, it adds the second optional parameter to determine which Dom element has changed. Therefore, if you know which part of the page is repainted, you can limit the area where the repainting occurs.

I should not be surprised if there is any corresponding mozanimationstarttime, because it is not very helpful if there is no next re-painting time information. Yes, but webkitcancelanimationframe () cancels the previously planned re-painting.

If you do not need accurate time differences, you can use the following method to create an animation for firefox4 and chrome10 +:

 
Function draw (timestamp) {// calculate difference since last repaint var drawstart = (timestamp | date. now (), diff = drawstart-starttime; // use diff to determine correct next step // reset starttime to this repaint starttime = drawstart; // draw again requestanimationframe (draw);} var requestanimationframe = Window. required requestanimationframe | window. webkitrequestanimationframe, starttime = Window. specified animationstarttime | date. now (); requestanimationframe (draw );

This mode uses an available method to create a loop animation with the idea of how much time it takes. Firefox uses the time code information, while Chrome is a time object that is not accurate by default. In this mode, the difference in time gives you an idea of how much time has passed, but it does not tell you when chrome will redraw the next time. However, this is better than the vague concept of how much time has passed.

Summary

The introduction of the mozrequestanimationframe () method plays an important role in promoting the history development of JavaScript animation and web. As mentioned above, the Javascript animation is almost the same as that in the early stage of JavaScript. As browsers gradually launch CSS transitions and animations, we are glad to see the attention of JavaScript-based animations, because these games based on <canvas> will become more important and more closely related to the cup. Know when JavaScript will try animation, and allow the browser to do more optimization, including stopping the process when the tab is in the background or when the power of the mobile device is too low.

The requestanimationframe () API is now being drafted by W3C and is being made part of the Web stage by Mozilla and Google. We are glad to see that these two groups are so quickly compatible (may not be completely.

Original post address

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.