The easing function requestAnimationFrame can better implement the basic knowledge of animation through browsers.

Source: Internet
Author: User
What is requestAnimationFrame? It has always been a question for all of us. The easing function requestAnimationFrame can better implement browser animation. Next we will introduce you in detail how to use the requestAnimationFrame function to write the easing function. I have learned a little before, however, I still don't know much about it, so I translated an article from a foreigner to learn and share it.

What is requestAnimationFrame?
Previously, we needed a timer for animation, and made some changes every interval in milliseconds. Now there is good news: browser vendors have decided to provide a special method for animation, that is, requestAnimationFrame (), and the browser-based layer can also be better optimized. However, this is just a basic API for animation, that is, it is not based on the style changes of DOM elements, it is not based on canvas, or WebGL. Therefore, we need to write the animation details by ourselves.

Why should we use it?
For the n animations simultaneously, the browser can optimize and optimize the original reflow and repaint N times to 1 time, thus achieving high-quality animation. For example, there are now JS-based animations, CSS-based transitions, or svg smil. plus, if a tab in the browser is running such an animation, you can switch to another tab or minimize it. In short, you cannot see it, and the browser will stop the animation. This will mean less CPU, GPU, and less memory consumption, which greatly prolongs the battery life.

How to use it?

The Code is as follows:


// Shim layer with setTimeout fallback
Window. requestAnimFrame = (function (){
Return window. requestAnimationFrame |
Window. webkitRequestAnimationFrame |
Window. Required requestanimationframe |
Window. oRequestAnimationFrame |
Window. msRequestAnimationFrame |
Function (/* function */callback,/* DOMElement */element ){
Window. setTimeout (callback, 1000/60 );
};
})();
// Usage:
// Instead of setInterval (render, 16 )....
(Function animloop (){
Render ();
RequestAnimFrame (animloop, element );
})();


Note: Here I use "requestAnimFrame", because the specification is still changing and I don't want to let it go.
RequestAnimationFrame API

The Code is as follows:


Window. requestAnimationFrame (function (/* time */time ){
// Time ~ = + New Date // the unix time
},/* Optional bounding elem */elem );


The Chrome and Firefox versions are provided first.

The Code is as follows:


Window. Define requestanimationframe ([callback]); // Firefox
Window. webkitRequestAnimationFrame (callback [, element]); // Chrome


Parameters:
Callback :( FF (optional, Chrome required)
The first parameter of the function to be called in the next repaint operation is the current time.
Element :( FF none)
It's actually a canvas, and the 'pa' is an animation. (The element that corresponds ally bounds the entire animation ). For canvas and WebGL, it is Element. For DOM nodes, you can ignore it. If you want to optimize it a little bit, you can also pass in a parameter.

Is it unreliable?
At present, there are some differences between Webkit implementation (available for nginx Safari and Chrome Dev Channel) and Mozilla implementation (available for FF4). Mozilla's implementation has a Bug. In fact, the number of frames in the FF animation is calculated as follows: 1000/(16 + N) fps, where N is the callback execution time, in milliseconds. If your callback execution time is 1000 ms, the maximum number of frames is only 1 FPS. If your callback execution time is 1 ms, the number of frames is almost 60 FPS. This bug will be fixed, maybe the next version of FF4. Chrome10 does not have the time parameter (added in m11. what is m11 ?), FF currently does not have the element parameter.
I read the bug of Firefox, which is probably:
FF's writable requestanimationframe () will never reach 60fps, even if your callback execution time is less than 1000/60 milliseconds. For example:

The Code is as follows:


Function callback (time ){
Window. Specify requestanimationframe (callback );
DoWork ();
}


If doWork () takes 1000/60 milliseconds, the number of frames is about 30fps. If setTimeout (callback, 16) is used for the same animation, the frame rate is 60fps. It seems that callback always starts to execute again about 16 ms after the callback execution is complete, instead of starting to execute again 16 ms after the callback starts to execute. If it is the latter and the computation is fast enough, the number of frames generated is 60 FPS.
If you are using standard control, the portal is here



Let's not talk much about it. First, let's use a classic animation function.:

The Code is as follows:


Function animate (element, name, from, to, time ){
Time = time | 800; // 0.8 seconds by default
Var style = element. style,
Latency = 60, // change every 60 ms
Count = time/latency, // number of changes
Step = Math. round (to-from)/count), // The number of changes in each step
Now = from;
Function go (){
Count --;
Now = count? Now + step:;
Style [name] = now + 'px ';
If (count ){
SetTimeout (go, latency );
}
}
Style [name] = from + 'px ';
SetTimeout (go, latency );
}


Regardless of the design limitations of this function, for example, you can only modify the style in px. From the implementation of functions, this can be a very classic animation concept. Its basic logic consists of the following parts:
Obtain the start value from and end value to, and calculate the number of changes to the value count and the number of changes each time based on the time required by the animation and the latency requirements for each detection interval.
Enable setTimeout (fn, latency); To step to the next detection.

In the next investigation, set the attribute step once. If the animation is not over yet, go back to Step 1 to continue the next investigation.
This function works well and serves thousands of sites and systems. In fact, the core of jQuery's animate function is nothing more than the setInterval function.
However, as the complexity of the system increases steadily, the animation effect is also increasing, and more attention is paid to the smoothness of the animation, which leads to some problems in the above functions. For example, if you enable 100 animation effects at the same time, according to the above function, it is obvious that 100 timers are running at the same time, and the scheduling between these timers will have a slight impact on the performance. Although in a normal environment, these influences do not have any relationship, but in an environment with High smoothness requirements such as animation, any minor impact may lead to poor user experience.

Under such circumstances, some developers have invented an animation framework based on unified frame management. They use a timer to trigger animation frames and different animations to register these frames, process the attribute changes of multiple animations on each frame. This reduces the timer scheduling overhead. However, developers of animation frameworks need to develop and maintain uniform frame management and provide APIs for listening frames.

Direct support of browsers
In the end, browser vendors discovered that this problem could actually be done by them, and there could be more optimizations Based on the browser layer, such:
For all DOM operations in a single detection, Layout and painting are performed only once.
If the animation element is hidden, the painting will not be used.
As a result, the browser began to launch an API called requestAnimationFrame. For this function, MDC related pages are described in detail. In short, this function has two usage methods:
Call the requestAnimationFrame function and pass a callback parameter. The callback function is called when the next animation frame is used.
Directly call this function without passing parameters to start the animation frame. When the next frame is triggered, the window. ondomainbeforepaint event is triggered simultaneously. You can register this event for animation.

Because the 2nd methods depend on Firefox events and the beforepaint event has not yet entered the standard, it is not recommended to use the 1st methods. In this case, our animation logic can be changed to the following:
Record the current startTime as the animation start time.
Request the next frame with the callback function.
When the next frame is triggered, the first parameter of the callback function is the current time, which is compared with startTime to determine the time interval ellapseTime.
Determine whether ellapseTime has exceeded the preset animation time. If the animation time is exceeded, the animation is ended.
Calculate the difference differ = to-from between the animation attributes, and then determine the step = differ/time * ellapseTime to be changed during ellapseTime.
Calculate the Math. round (from + step) that should be changed and assign a new value to the style.
Continue to request the next frame.

New animation Functions
The following is a brand new animation function:

The Code is as follows:


Function animate (element, name, from, to, time ){
Time = time | 800; // 0.8 seconds by default
Var style = element. style,
StartTime = new Date;
Function go (timestamp ){
Var progress = timestamp-startTime;
If (progress> = duration ){
Style [name] = to + 'px ';
Return;
}
Var now = (to-from) * (progress/duration );
Style [name] = now. toFixed () + 'px ';
RequestAnimationFrame (go );
}
Style [name] = from + 'px ';
RequestAnimationFrame (go );
}


At this point, there is still a problem, that is, not every browser supports the requestAnimationFrame function, so we can make a simple correction.
According to Firefox's features, the maximum FPS provided by javasrequestanimationframe is 60, which is adjusted based on the computing time of each frame. For example, one second is used for computing each frame, then he will only provide 1 FPS animation effect.
Chrome's later version also implements this function, which is called webkitRequestAnimationFrame. In the future, there will be Opera's oRequestAnimationFrame and IE's msRequestAnimationFrame, so here we will make a simple compatibility processing:

The Code is as follows:


RequestAnimationFrame = window. requestAnimationFrame |
Window. Required requestanimationframe |
Window. webkitRequestAnimationFrame |
Window. msRequestAnimationFrame |
Window. oRequestAnimationFrame |
Function (callback) {setTimeout (callback, 1000/60 );};

Related Article

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.