The knowledge points that must be clarified about high-performance animations

Source: Internet
Author: User
Tags unsupported

Question 1:What is the relationship between 60Hz and 60fps?

There is no relationship. FPS represents the frequency at which the GPU renders the screen, and Hz indicates how often the display is refreshed. A static picture, you can say that the picture fps is 0 frames per second, but absolutely not say that the screen refresh rate is 0Hz, that is, the refresh rate does not change with the content of the image. The game is good browser, we talk about dropped frames, refers to GPU rendering screen frequency reduction. such as falling to 30fps or even 20fps, but because of the visual persistence principle, we see the picture is still motion and coherence.

The above also ignores the time cost of screen refresh screens. The problem arises from the inconsistent frequency of the GPU render screen and the screen refresh frequency : If the GPU renders a frame of time that is shorter (faster) than when the display refreshes a picture Then when the display has not finished refreshing a picture, the GPU rendered another picture has been delivered and overwritten the previous one, resulting in screen tearing, that is, the top half is the previous picture, the lower half is the next picture:

In the JavaScript high-performance animation and page rendering of this article, for example, in 14ms, then only the number of frames added up to more than 16.7ms, then will certainly drop the frame, and each frame delay time is 2.7ms, so 16.7/2.7= 6 that is, in the sixth frame will definitely drop frames!! If the update frequency is 16ms, then each frame delay is 0.7ms, then the 16.7/0.7=23.85 that is 24 frames will definitely drop frames!!! and if the animation setinterval time interval is smaller, then the number of dropped frames will be more!

The way to solve this problem in PC games is to turn on vertical synchronization (V-sync), which is to let the GPU compromise, GPU rendered images must be between two refreshes of the screen, and must wait for the screen to send a vertical sync signal. But there's also a price to pay: lower the output frequency of the GPU and reduce the number of frames on the screen. So that you feel the "card" when playing a game that requires a high number of frames (such as racing, first-person shooter), because the frame is dropped. (The problem with dropped frames is the lag, because the other tasks are running)

But if your callback function is really serious, the RAF can still do something for you. For example, when it finds that it cannot maintain a 60fps frequency, it will reduce the frequency to 30fps, at least to keep the number of frames stable and keep the animation coherent.

Question 2:ui How is the engine and JS engine mutually exclusive?

function Jank (second) {    var start = +new Date ();    while (start + second * > (+new Date ())) {}}div.style.backgroundcolor = "red";//Some long run Task//ui engine and JS engine mutually exclusive, first Call the UI engine, then the JS engine, and finally the UI engine Jank (5);d Iv.style.backgroundColor = "Blue";
Regardless of running the above code in any browser, you will not see the div turn red, the page will usually be suspended for 5 seconds, then the container turns blue. This is because the browser always has only one thread running (so to understand, because the JS engine is mutually exclusive to the UI engine,The browser will not update the UI immediately, but will be in a queue to modify the batch update method to complete, unless it is a special property such as Innerwidth, or else will be executed first after the JS code)。 Although you tell the browser that the div background color should be red, it is still executing the script at this point and cannot invoke the UI thread.
var div = document.getElementById ("foo"); var currentwidth = div.innerwidth; Div.style.backgroundColor = "Blue";//The UI is not updated immediately, but will wait until after the end of the JS run to execute the/do some "long running" task, like sorting data
We can use the following code to optimize:

Requestanimationframe (function () {    var el = document.getElementById ("foo");    var currentwidth = el.innerwidth;    El.style.backgroundColor = "Blue";}); /Do some ' long running ' task, like sorting data
The code to update the background color is too early, according to the previous example, we know that even if you tell the browser I need to update the background color, the browser will at least wait until the JS run to invoke the UI thread;(Delay this part of the code)Suppose that the long runing code in the latter part starts some asynchronous code, such as settimeout or AJAX requests or web-worker, which should be as early as possible (let the subsequent code execute immediately)。
What are the drawbacks of the problem 3:window.onscroll

Events such as scroll,resize are triggered very frequently, and if too much code is put into this class of callbacks, the scrolling of the page is delayed or even unresponsive. Therefore, this kind of code should be separated out, placed in a timer, there are intervals to check whether to scroll, and then do the appropriate processing. The principle is the same, in order to optimize performance, in order to prevent the browser suspended animation, the need for long-running code decomposition into a small segment execution, allowing the browser to have time to respond to other requests.

var didscroll = false;$ (window). Scroll (function () {    didscroll = true;}); SetInterval (function () {    if (didscroll) {        didscroll = false;        Check your page position and then        //Load in more results    }}, 250)
We can also use Requestanimationframe to complete the process:

var latestknownscrolly = 0;function onscroll () {    latestknownscrolly = window.scrolly;} function Update () {    requestanimationframe (update);    var currentscrolly = latestknownscrolly;    Read offset of DOM elements    //And compare to the currentscrolly value    //Then apply some CSS classes    //To The Visible items}//kick offrequestanimationframe (update);
This way regardless of whether our latestknownscrolly has changed, that is, whether there is a rolling, then we willStop it.Execution of the Update method, which is obviously unnecessary, such as the user has been on a page for half an hour without scrolling, this time the calculation is not necessary.

var latestknownscrolly = 0, ticking = false;//calculates the current scrolling distance each time it scrolls, and also uses Requestanimationframe to update the contents of the next frame!function onscroll (    ) {latestknownscrolly = window.scrolly; Requesttick ();}        function Requesttick () {if (!ticking) {requestanimationframe (update); If the < Next frame execution is completed > this time again you can continue to listen to the scrolling event, instead of the example above each scroll//So, even if you have scrolled an element, but because this time the update is not executed, that is, the previous frame has not been executed, Therefore it will not continue to add the callback function to the inside, but the most recent distance to scroll is to get to the} ticking = true;}    function Update () {//Reset the tick so we can//capture the next onscroll ticking = false;    var currentscrolly = latestknownscrolly; Read offset of DOM elements//And compare to the currentscrolly value//Then apply some CSS classes//To TH E Visible items}window.addeventlistener (' scroll ', onscroll, false); 
Note: The constant scrolling here does not insert multiple upate methods, because ticking is true, so only wait until the next frame executes the Update method to continue inserting upate, but we should note that this time the vertical scrolling distance of the page is changing!
Question 4: How do we postpone a function to the next frame to execute

(function (h5) {if (!h5) throw new Error ("animationFrame.h5ive:core.h5ive required."); var RAF = (Window.requestanimationframe | | window.msrequestanimationframe | | Window.mozrequestanimationframe | | Window.webkitrequestanimationframe | | Window.orequestanimationframe), CAF = (Window.cancelanimationframe | | Window.mscancelanimationframe | | Window.mscancelrequestanimationframe | | Window.mozcancelanimationframe | | Window.mozcancelrequestanimationframe | | Window.webkitcancelanimationframe | | Window.webkitcancelrequestanimationframe | | Window.ocancelanimationframe | |     Window.ocancelrequestanimationframe), Publicapi, q_ids = {}; Generates a unique ID value function QID () {var id;do {id = Math.floor (math.random () * 1E9);} while (ID in q_ids); return ID;} Insert Next frame, return this unique number function queue (CB) {var qid = qid ();//Use this unique ID to place a callback function in the callback function. Q_ids[111111113334]=12,q_ids[456789098]=24. The call returns a unique integer value (which is returned by the browser) that can be canceled by this integer value!!! Q_IDS[QID] = RAF (function () {delete q_ids[qid];cb.apply (publicapi,arguments);//The parameter in the callback function of this element is in addition to the callbackThe parameter passed to the queue outside of the function}); return qid;} Insert Next frame, the function of the queue is to put the function in the next frame to execute, but this qid is globally unique!function Queueafter (CB) {var qid;qid = queue (function () {//Do our own RAF Call here because we want to re-use the same ' qid ' for both framesq_ids[qid] = RAF (function () {Delete q_ids[qid];cb.apply (p ublicapi,arguments);}); return qid;} Cancels a callback function cancel (QID) {if (QID in Q_ids) {CAF (q_ids[qid]);d elete q_ids[qid];} return PUBLICAPI;}     function unsupported () {throw new Error ("' Requestanimationframe ' not supported."); If the RAF is supported then go here the logic if (RAF && cAF) {Publicapi = {queue:queue,queueafter:queueafter,cancel:cancel};} else {Publicapi = {queue:unsupported,queueafter:unsupported,cancel:unsupported};} H5.animationframe = Publicapi;}) (THIS.H5);
Because each RAF function returns a unique integer, the integer is determined by the browser. With this integer we can cancel a call.

             function Queue (CB) {var qid = qid ();//Use this unique ID to place a callback function in the callback function. Q_ids[111111113334]=12,q_ids[456789098]=24. The call returns a unique integer value (which is returned by the browser) that can be canceled by this integer value!!! Q_IDS[QID] = RAF (function () {delete q_ids[qid];cb.apply (publicapi,arguments);//The parameter in the callback function of this element is the parameter passed to the queue in addition to the callback function}) ; return qid;}
This function defers the function to the next frame execution, and each time it produces a unique QID value as the key of the array, and the value is a unique value returned by the RAF function. The next frame after this function is executed then we will clear the corresponding key and value from this array, but the delete is deleted, so we will leave undefined!

Reference documents:

Deep understanding of Requestanimationframe

Explore some ways to make JavaScript animations smooth

The knowledge points that must be clarified about high-performance animations

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.