Why is it stuck? There is a premise that must be mentioned. Front-end developers all know that the browser runs in a single thread. But we need to clarify the following concepts: single thread, main thread and synthesis thread. Although the browser executes JS in a single thread (note, it is execution, not that the browser has only one thread, but running), in fact, the browser has two important execution threads, which work together to render a web page: the main thread and the synthesis thread. In general, the main thread is responsible for: running JavaScript; calculating the CSS styles of HTML elements; layout of the page; drawing elements into one or more bitmaps; and handing these bitmaps to the synthesis thread. Accordingly, the composition thread is responsible for: drawing the bitmap to the screen through the GPU; notifying the main thread to update the bitmap of the visible or soon-to-be-visible part of the page; calculating which part of the page is visible; calculating which part is about to become visible when you scroll the page; and moving elements of the corresponding position into the visible area when you scroll the page. So why does the animation freeze? The reason is that the scheduling of the main thread and the synthesis thread is unreasonable. Let's talk about the reasons for unreasonable scheduling in detail: When using height, width, margin, and padding as transition values, the browser main thread will have a heavy workload. For example, when rendering from margin-left: -20px to margin-left: 0, the main thread needs to calculate the styles of margin-left: -19px, margin-left: -18px, all the way to margin-left: 0. Moreover, each time the main thread calculates the style, the synthesis process needs to draw it to the GPU and then render it to the screen. A total of 20 main thread renderings and 20 synthesis thread renderings are performed, 20+20 times, for a total of 40 calculations. The rendering process of the main thread can refer to the process of browser rendering web pages:
That is to say, the main thread needs to execute the calculations of the four stages of Scripts, Render Tree, Layout and Paint every time. And if transform is used, for example, tranform:translate(-20px,0) to transform:translate(0,0), the main thread only needs to perform one tranform:translate(-20px,0) to transform:translate(0,0), and then the synthesis thread will convert -20px to 0px once, so the total calculation is 1+20. Some people may say that this is only an improvement of 19 times, what good performance improvement is there? Assume 10ms at a time. This reduces the time consumption by about 190ms. Some people may say, it’s crap, only 190ms, it doesn’t matter. So what if margin-left is from -200px to 0, 10ms at a time, 10ms 199≈2s. Some people will say, it’s trash, it’s only 2s, it doesn’t matter. Did you forget about single threading? 2s=6s, which means a performance improvement of 6s. Since the data is guesswork, its authenticity is not considered for the time being. In order to enhance the persuasiveness of this article, I will use an example to prove my point. Let's take a look at it together. In the front end, animation is used to implement the home page animation transition in the H5 page. It is a very simple effect. A customer service avatar is loaded on the home page, first enlarged, stayed for 700ms, and then shrunk to the top. The code is as follows: <!DOCTYPE html> <html> <head lang="en"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=1" > <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script> <title>Homepage loading animation</title> <head> <style> .welcome-main{ display: none; padding-bottom: 40px; } .top-info{ width: 100%; position: absolute; left: 0; top: 93px; } .wec-img{ width: 175px; height: 175px; position: relative; padding: 23px; box-sizing: border-box; margin: 0 auto; } .wec-img:before{ content: ''; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: url("./images/kf-welcome-loading.jpg"); background-size: 100%; } .wec-img .img-con{ width: 100%; height: 100%; border-radius: 50%; /*box-sizing: border-box;*/ background: url("./images/kf_1.jpg"); background-size: 100%; padding: 1px; } .wec-img .img-con img{ width: 100%; height: 100%; border-radius: 50%; } .loaded .wec-img{ -webkit-transform-origin: center top; } .loading.welcome-main{ display: block; } .loading .wec-img{ -webkit-animation:fadeIn .3s ease both; } .loading .wec-img:before{ -webkit-animation:rotate .6s .2s linear both; } .loaded .top-info{ -webkit-animation:mainpadding 1s 0s ease both; } .loaded .wec-img{ -webkit-animation:imgSmall 1s 0s ease both; } @-webkit-keyframes mainpadding{ 0%{-webkit-transform:translateY(0) } 100%{-webkit-transform:translateY(-87px) } } @-webkit-keyframes imgSmall{ 0%{ width: 175px; height: 175px; padding: 23px; } 100%{ width: 60px; height: 60px; padding: 0; } } @-webkit-keyframes fadeIn{ 0%{opacity:0;-webkit-transform:scale(.3)} 100%{opacity:1;-webkit-transform:scale(1)} } @-webkit-keyframes rotate{ 0%{opacity:0;-webkit-transform:rotate(0deg);} 50%{opacity:1;-webkit-transform:rotate(180deg);} 100%{opacity:0;-webkit-transform:rotate(360deg);} } </style> <body> <div class="welcome-main"> <div class="top-info"> <div class="wec-img"><p class="img-con"><img src="" alt=""></p></div> </div> </div> <script> $('.welcome-main').addClass('loading'); setTimeout(function(){ $('.hi.fst').removeClass('loading'); $('.welcome-main').addClass('loaded'); },700); </script> </body> </html> The test was ok on Chrome, but when submitting the test to QA, it was found that some models, such as Huawei (system 4.2) and OPPO (system 5.1), had lags. I was puzzled, so I referred to the article "In-depth understanding of browser performance issues of CSS animations and transitions" and changed the animation element in the image scaling to transform, as follows @-webkit-keyframes imgSmall{ 0%{ -webkit-transform:scale(1); } 100%{ -webkit-transform:scale(.465); } } Sure enough, the lag problem was solved. The article In-depth understanding of the browser performance issues of CSS animations and transitions explains that modern browsers usually have two important execution threads that work together to render a web page: the main thread and the synthesis thread. In general, the main thread is responsible for: running JavaScript; calculating the CSS styles of HTML elements; layout of the page; drawing elements into one or more bitmaps; and handing these bitmaps to the synthesis thread. Accordingly, the composition thread is responsible for: drawing the bitmap to the screen through the GPU; notifying the main thread to update the bitmap of the visible or soon-to-be-visible part of the page; calculating which part of the page is visible; calculating which part is about to become visible when you scroll the page; and moving elements of the corresponding position into the visible area when you scroll the page. Suppose we want an element's height to change from 100 px to 200 px, like this: div { height: 100px; transition: height 1s linear; } div:hover { height: 200px; } The main thread and the synthesis thread will perform corresponding operations according to the following flowchart. Note that operations in the orange box may be time-consuming, while operations in the blue box are faster. And use transform:scale to achieve div { transform: scale(0.5); transition: transform 1s linear; } div:hover { transform: scale(1.0); } The process is as follows: That is, using transform, the browser only needs to generate the bitmap of the element once and submit it to the GPU for processing when the animation starts. After that, the browser does not need to do any layout, drawing, or bitmap submission operations. Thus, the browser can take full advantage of the GPU to quickly draw the bitmap in different positions, perform rotation or scaling. In order to confirm this theory from an order of magnitude, I opened Chrome's Timeline to view the page FPS Among them, when using height as an animation element, the FPS during the switching process is only 44. We know that 60 frames per second is the most suitable interaction for the human eye. If it is less than 60, the human eye can clearly feel it, which is why there is a freeze. The time spent on rendering and painting is as follows: Let's look at using transform:scale FPS reached 66, and rendering and painting time was reduced by 3 times. So far the problem was solved. A few days later, I saw an article about how to solve the "stuttering" problem of Chrome animations. I found that I could also optimize the animations by turning on hardware acceleration, so I tried it again. webkit-transform: translate3d(0,0,0); -moz-transform: translate3d(0,0,0); -ms-transform: translate3d(0,0,0); -o-transform: translate3d(0,0,0); transform: translate3d(0,0,0); Something amazing happened, the FPS reached 72:
Try to use transform as animation, avoid using height, width, margin, padding, etc. When the requirements are higher, you can enable GPU hardware acceleration in the browser. The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM. |
<<: Operations of communication between Docker containers and external network communication
>>: iframe adaptive size implementation code
Preface Samba is a free software that implements ...
0. Overview Zabbix is an extremely powerful ope...
When I used g++ to compile the cpp file for the f...
This article shares the specific code of vue unia...
1. Install JDK 1.1 Check whether the current virt...
This article example shares the specific code of ...
Each of these 16 sites is worth reading carefully,...
Today I found this prompt when I was running and ...
1. Introduction MySQL comes with a replication so...
This article records the installation tutorial of...
The operating system for the following content is...
Table of contents Introduction Child Process Crea...
1. Check the maximum number of open files in the ...
MultiTail is a software used to monitor multiple ...
Table of contents 1. What is a window function? 1...