Using Requestanimationframe to achieve JS animation performance good _javascript skills

Source: Internet
Author: User
Tags diff memory usage setinterval time interval

Using Requestanimationframe to achieve a good performance JS animation. First give you a brief introduction to the next Requestanimationframe than SetTimeout, setinterval have what advantages?

Example one:

Requestanimationframe has two main advantages over settimeout and setinterval:
1. Requestanimationframe will centralize all DOM operations in each frame, complete in a redraw or reflow, and redraw or reflow time intervals closely follow the browser's refresh rate, typically 60 frames per second.
2, in hidden or invisible elements, requestanimationframe will not be redrawn or reflow, which of course means less cpu,gpu and memory usage.
Like SetTimeout, SetInterval, Requestanimationframe is a global function. When Requestanimationframe is invoked, it asks the browser to redraw it at its own frequency, receiving a callback function as an argument, calling the function when the browser is about to be redrawn, and giving the function the time to call the callback function as an argument. Because Requestanimationframe is only one-off, so if you want to achieve animation effect, you must continuously call Requestanimationframe, as we do with settimeout to achieve animation. The Requestanimationframe function returns a resource identifier that can be passed as a parameter to the Cancelanimationframe function to cancel the requestanimationframe callback. How, not also with settimeout cleartimeout very similar AH.
So, so to speak, Requestanimationframe is a performance optimized version, designed specifically for animation settimeout, the difference is that Requestanimationframe does not specify the time that the callback function runs, Instead, it performs the callback with the refresh rate built into the browser, which, of course, achieves the best effect of the animation that the browser can achieve.
At present, each support Requestanimationframe browser some still own private implementation, so must prefix, for not support Requestanimationframe Browser, we can only use settimeout, Because the two are used almost the same way, the compatibility of the two is not difficult. For browsers that support Requestanimationframe, we use requestanimationframe, and we don't support graceful demotion using traditional settimeout. By encapsulating them, you can get an API that is unified and compatible with each big browser.
Code can come here to view: https://gist.github.com/chaping/88813f56e75b0fd43f8c

var lasttime = 0; var prefixes = ' WebKit moz ms O '. Split (');
Each browser prefix var requestanimationframe = window.requestanimationframe;
var cancelanimationframe = Window.cancelanimationframe;
var prefix; By traversing each browser prefix, you get requestanimationframe and Cancelanimationframe in the current browser implementation form for (var i = 0; i < prefixes.length; i++) {if (Requestanimationframe && Cancelanimationframe)
 {break;
 } prefix = prefixes[i]; Requestanimationframe = Requestanimationframe | |
 window[prefix + ' requestanimationframe ']; Cancelanimationframe = Cancelanimationframe | | window[prefix + ' cancelanimationframe '] | |
window[prefix + ' cancelrequestanimationframe ']; //If the current browser does not support Requestanimationframe and cancelanimationframe, it will retire to settimeout if (!requestanimationframe | |!).
 Cancelanimationframe) {requestanimationframe = function (callback, Element) {var currtime = new Date (). GetTime (); 
 In order to make settimteout as close as possible to the effect of 60 frames per second var timetocall = Math.max (0-(currtime-lasttime)); var id = window.settimeout(function () {callback (currtime + Timetocall);
 }, Timetocall);
 Lasttime = Currtime + Timetocall;
 return ID;
 };
 Cancelanimationframe = function (id) {window.cleartimeout (ID);
}; 
//Get compatible with each browser API window.requestanimationframe = Requestanimationframe;
 Window.cancelanimationframe = Cancelanimationframe;

This way we can use Requestanimationframe and cancelanimationframe on all browsers.
Here is a simple example to illustrate how to use requestanimationframe for animation, the following code will be the ID of the demo Div animation to the right to move to the 300px

<div id= "Demo" style= "Position:absolute; width:100px; height:100px; Background: #ccc; left:0; top:0; " ></div>
<script>
var demo = document.getElementById (' demo ');
function Rander () {
 demo.style.left = parseint (demo.style.left) + 1 + ' px ';/move 1px
}
to the right of each frame Requestanimationframe (function () {
 rander ();
 Stop
 if (parseint (demo.style.left) <=300) requestanimationframe (Arguments.callee) after more than 300px;
</script>


Example two:

All along, JavaScript animations are implemented through timers and intervals. Although the use of CSS transitions and animations makes web development animation more convenient, over the years the JavaScript based animation has rarely changed. It was not until the release of Firefox 4 that the first approach to improving JavaScript animation was introduced. But to be fully aware of the improvements, this helps us understand how web animations evolve and improve.
Timers Timer
The first pattern for creating animations is to use chained settimeout () calls. For a long time in Netscape 3′s Hayday, developers remember a fixed, up-to-date market status bar that is ubiquitous on the web, usually similar to this:

(function () { 
 var msg = "New advertisement", 
 len = = 
 0, 
 padding = msg.replace (/./g, ""). substr (0,len), 
 fin almsg = padding + msg; 
 function UpdateText () { 
 var curmsg = finalmsg.substr (pos++, Len); 
 Window.status = curmsg; 
 if (pos = = finalmsg.length) {pos = 0;} 
 settimeout (UPDATETEXT, MB); 
 settimeout (UPDATETEXT, MB); 
}) (); 

If you want to test this code in a browser, you can create a new
Tags are used to simulate window.status, for example: newsticker example
This annoying web model was later resisted by Window.status, but with the release of Explorer 4 and Netscape 4, the browser first gave developers more control over page elements, and this technology came back. This shows a new animation pattern that uses JavaScript to dynamically change 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.getelementbyidx_x ("status"); 
 Div.style.width = (parseint (div.style.width, ten) + 5) + "%"; 
 if (div.style.width!= "100%") {settimeout (updateprogress, MB);} 
 } 
 settimeout (updateprogress, MB); 
}) (); 

Although the animation is different on the page, the rationale is the same: Make a change, update the page with the settimeout () interval, and then settimeout the next change, the process repeats until the animation is complete (see progress bar animation), and early status bar animations are the same technology , but the animation is not the same.
Interval animation intervals
With the successful introduction of the animation into the Web, a new exploration begins. An animation is no longer satisfied, now requires more than one animation. The first attempt to create multiple animation loops for each animation, using settimeout () to create multiple animations in an earlier browser is a bit complicated, so developers start using setinterval () to create a single animation loop to manage all the animations on the page, A basic animation using Wetinterval () is like this:

(function () { 
 function updateanimations () { 
 updatetext (); 
 UpdateProgress (); 
 } 
 SetInterval (updateanimations, MB); 
}) ();

Create a small animation library, the Updateanimations () method loops through each animation (and sees a news stock and progress bar running together) and makes appropriate changes. If there is no animation to update, the method can exit without doing anything, or even stop the animation loop until more animation updates are ready.
The tricky question about the animation problem is how long the delay should be. The interval must be short enough so that different animations can flow smoothly, not on the one hand long enough to enable the browser to complete rendering. Most browsers have a refresh rate of 60HZ, that is, 60 refreshes per second, and most browsers refresh less often than this, because they know that the end user is not getting a better experience.
In view of this, the optimal time interval for fluent animation is 1000 milliseconds/60, about 17ms. At this frequency you will see the smooth animation, it is because you are the most close to the browser to achieve the frequency. Compared to previous animations, you'll find that 17ms-interval animations are smoother and faster (because animations are updated more frequently without any other modifications), multiple animations may need to be throttled to prevent 17ms animations from completing too quickly.
Problem
Even though the setinterval () based animation cycle is more efficient than multiple sets of animation loops using settimeout (), there is a problem. Neither setinterval () nor settimeout () can achieve precision, which means that the second parameter you specify simply indicates when the code will be added to the browser's potentially executing UI thread queue. If there are other jobs in the queue before that, the code will not execute until he finishes. In short, the millisecond delay does not mean when the code executes, but rather when the code is added to the queue. If the UI thread is busy or the user action is being processed, the code will not be executed immediately.
The key to smooth animation is to understand when the next frame is executed, until now there is no way to guarantee that the next frame will be drawn in the browser. With the growing popularity and emergence of new browser-based games, developers are increasingly frustrated by the setinterval () and settimeout () inaccuracies.
The browser's timer resolution exacerbates this problem, the timer is not accurate for milliseconds, and here are some common timer resolutions:
Internet Explorer 8 and earlier 15.625ms
Internet Explorer 9 and later 4ms.
Firefox and Safari ~10ms.
Chrome has a timer 4ms.

IE has a resolution of 15.625 before version 9, so any value between 0~15 may be 0 or 15, but there is no difference. IE9 's timer resolution is improved to 4ms, but it is also not specific when it comes to animations, with Chrome's timer resolution of 4ms,firefox and Safari's 10ms. So even if you set the interval to the best display, you just get the approximate value.
Mozrequestanimationframe
Mozilla's Robert O ' Callahan is thinking about the problem and has come up with a unique solution. He points out that the advantage of CSS transitions and animations is that browsers know which animations will occur, so they get the correct intervals to refresh the UI. While JavaScript animations, browsers do not know that animations are happening. His solution is to create a mozrequestanimationframe () method to tell the browser which JavaScript code is executing, which allows the browsing to be optimized after executing some code.
The Mozrequestanimationframe () method accepts a parameter, which is a function called before the screen is redrawn. This function is used to change the appropriate DOM style under the build, and these changes are used in the next redraw. You can call Mozrequestanimationframe () in the same way as settimeout (), for example:

function UpdateProgress () { 
 var div = document.getelementbyidx_x ("status"); 
 Div.style.width = (parseint (div.style.width, ten) + 5) + "%"; 
 if (div.style.left!= "100%") { 
 mozrequestanimationframe (updateprogress); 
 } 


Mozrequestanimationframe (UpdateProgress);
Since Mozrequestanimationframe () only runs the 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, is an example of a very fluent animation enhancement.
As a result, Mozrequestanimationframe () solves the problem that browsers do not know what JavaScript animations are performing and don't know how much is the right interval, but it is also the solution for not knowing when your code will actually be executed.
The function passed to Mozrequestanimationframe () is actually the time code (calculated in milliseconds from January 1, 1970) When the next redraw occurs. This is a very important point: Mozrequestanimationframe () actually lists the points that will be redrawn and tells you where they are. So you can decide how to better adjust your animation.
To get the last time to redraw the past, you can query Mozanimationstarttime, which contains the time code that was redrawn in the past. Subtracting this value when passing the callback calculates the time it takes to redraw the screen again. The typical patterns for using these values are 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 
 Mozrequestanimationframe (draw); 
} 
var starttime = mozanimationstarttime; 
Mozrequestanimationframe (Draw); 

The key is when the first time is not through the callback call, Mozanimationstarttime is the time that passes through the Mozrequestanimationframe (). If it is in a callback function, the mozanimationstarttime is the average of the time code passed in by the parameter.
Webkitrequestanimationframe
When many people are hot and loyal to Chrome, the Webkitrequestanimationframe () method is created. This version is slightly different from the Firefox version in two ways. On the one hand, it does not pass the time code through the callback function, you will not know when the next redraw occurs, on the other hand, it adds a second optional parameter to determine which DOM element has changed. So, if you know what part of the page the redraw occurs on, you can limit the area where the redraw occurred.
Should not be surprised, there is no corresponding mozanimationstarttime, because if there is no next redraw time information is not very useful. There, just Webkitcancelanimationframe () canceled the redraw that was planned before.
If you don't need exact time differences, you can create an animation for Firefox4 and chrome10+ in the following ways:

 function draw (timestamp) {//calculate difference since last repaint var drawstart = (t Imestamp | | 
 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.mozrequestanimationframe | | Window.webkitrequestanimationframe, StartTime = Window.mozanimationstarttime | | 
Date.now (); 
Requestanimationframe (Draw); 

This pattern uses the methods available to create looping animations that take a long time to the idea. Firefox uses time code information that is useful, and chrome defaults to a less-than-accurate time object. When using this pattern, the difference in time gives you an idea of how much time has passed, but it won't tell you when Chrome's next redraw is now. But this is better than the vague notion of how much time has passed. The
Summary
Mozrequestanimationframe () method is an important part of promoting JavaScript animation and the web's historical development. As mentioned earlier, the state of JavaScript animation is almost the same as the beginning of JavaScript. As browsers gradually introduce CSS transitions and animations, it's nice to see the focus of JavaScript based animations, which will become more important and more connected to the cup in the game-based arena. Knowing when JavaScript is trying to animate allows the browser to do more optimization, including stopping the process when the tab is in the background or when the mobile device is low. The
Requestanimationframe () API is now being drafted by the consortium to make a new bill, and is being made by Mozilla and Google as part of the web's big stage. It is nice to see the two groups being so quickly compatible (perhaps not entirely) implemented.
Requestanimframe uses
to perform only one layout and paint for all operations of the DOM in a single reconnaissance.
If an animated element is hidden, it is no longer going to paint.

Window.requestanimframe = (function () {return 
 Window.requestanimationframe | | 
 Window.webkitrequestanimationframe | | 
 Window.mozrequestanimationframe | | 
 Window.orequestanimationframe | | 
 Window.msrequestanimationframe | | 
 Function (callback) { 
  window.settimeout (callback, 1000/60); 
 };} 
) (); 
Call 
function Animationloop (elem) { 
 requestanimframe (animationloop); 
Logic 
} 
Or
window.requestanimframe = (function (w, R) { 
 w[' r ' +r] = w[' r ' +r] | | w[' WEBKITR ' +r] | | w[ ' MOZR ' +r] | | w[' MsR ' +r] | | w[' OR ' +r] | | function (c) {w.settimeout (c, 1000/60);}; 
 Return w[' R ' +r]; 
} (Window, ' equestanimationframe '); 

The above two pieces of code examples to explain the use of requestanimationframe to achieve JS animation performance Good, I hope you like.

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.