1

background

Front-end today is a very broad profession. As a front-end, we not only have to develop management systems and data centers, but also deal with scenarios such as annual report development and festival activities. Not only must be able to add, delete, modify and search, write forms, but also have the ability to develop animations, H5 games, etc. Being able to make very cool animation effects is also a unique sense of achievement in the front end. So, let's start with the implementation of animation, understand browser rendering, and how to improve the performance of animation.

Let's first look at 2 H5 cases:
【One mirror to the end】

filefile <->Mobile phone scanning experience

【annual report】

file
file
file

【Other H5 Excellent Cases】
https://www.h5anli.com

The first part of common animation implementation methods

1.1 gif implementation

file

definition:
The data of the GIF file is a continuous tone lossless compression format based on the LZW algorithm. The feature of the gif format is that a gif file can store multiple color images. When the data is read out one by one and displayed on the screen, it can form a Simple animation.
Up to 256 colors are supported. Because of this feature, GIF is more suitable for pictures with less color, such as page cartoon icons, logos, etc.

use:

 ![file](/img/bVcZPme)

advantage:
1. The production cost is very low;
2. Good compatibility;
3. It is convenient to develop and use.

shortcoming:
1. In terms of image quality: less color support, serious image burrs;
2. Interaction: The playback and pause of animation cannot be controlled, and there is no flexibility;
3. Size: Due to lossless compression, each frame is completely saved, resulting in a large file.

1.2 css3 complementary frame animation

1.2.1 transition transition animation

use:

 .box {
    border: 1px solid black;
    width: 100px;
    height: 100px;
    background-color: #0000ff;
    transition: width 2s, height 2s, background-color 2s, transform 2s;
}

.box:hover {
    background-color: #ffcccc;
    width: 200px;
    height: 200px;
    transform: rotate(180deg);
}

Scenes:

Often used with :hover, :active and other pseudo-classes to achieve corresponding animation effects.

1.2.2 animation key frame animation

use:

 .bounce1 {
    left: -40px;
    animation: bouncy1 1.5s infinite;
}
.bounce2 {
    left: 0;
    animation: bouncy2 1.5s infinite;
}
.bounce3 {
    left: 40px;
    animation: bouncy3 1.5s infinite;
}
@keyframes bouncy1 {
    0% {
        transform: translate(0px, 0px) rotate(0deg);
    }
    50% {
        transform: translate(0px, 0px) rotate(180deg);
    }
    100% {
        transform: translate(40px, 0px) rotate(-180deg);
    }
}

Scenes:
For example: loading display, the code is as above.

advantage:
1. There is no need to record every frame, and it is convenient to develop through key frame setting;
2. The implementation is simple, usually the UI can be directly given to the css file, and the front-end only needs to be imported [pay attention to screen adaptation on the mobile side].

shortcoming:
1. CSS has no animation interaction and cannot know the current animation execution stage;
2.transition: needs to be triggered and cannot be played automatically;
3. The animation compatibility needs to be prefixed, which leads to the exponential increase in the amount of code;
4. For the implementation of complex animation, the imported css file is too large, which affects the rendering tree generation of the page, thus blocking rendering. For example, to achieve the effect of a cash cow, if the CSS file reaches 100kb, it is necessary to take some necessary compression methods to reduce the file size.

1.3 js frame by frame animation

The principle of JS animation is to draw animation frames through setTimeout or requestAnimationFrame methods, so as to dynamically change the display properties of graphics in web pages (such as DOM style, canvas bitmap data, SVG object properties, etc.), and then achieve the purpose of animation.

demo1:
------- js implements a square moving animation from left to right -----

  1. setTimeout implementation

     const element2 = document.getElementById('raf2');
    const btn2 = document.getElementById('btn2');
    let i = 0;
    let timerId;
    function move () {   
     element2.style.marginLeft = i + 'px'
     timerId = setTimeout(move, 0)
     i++;
     if (i > 200) {
         clearTimeout(timerId)
     }
    }
    btn2.addEventListener('click',function () {
     move()
    })
  2. requestAnimationFrame implementation

     const element = document.getElementById('raf');
    const btn1 = document.getElementById('btn1');
    let r = 0;
    let rafId;
    function step () {
     element1.style.marginLeft = r+ 'px';
     rafId = window.requestAnimationFrame(step);
     r++;
     if (r > 200) { // 在两秒后停止动画
         cancelAnimationFrame(rafId);
     }
    }
    btn1.addEventListener('click', function () {
     step();
    })

It can be seen that the implementation method is to control the margin-left style of the dom and perform animation.

Question 1.1: The execution of setTimeout is very fast as seen in demo1. Why is this? Please look back

The second part of how browser rendering and animation rendering

2.1 The frame principle of the browser

Question 2: When the url is entered into a page and displayed, what process does it go through?

Here we ignore the steps before the http request for static files, and focus on how the browser renders the frame to find out how the browser renders the animation.

file

With the help of chrome-performance [execute raf.html], you can also see the annotations in the performance at different stages in the above figure. ⚠️ NOTE: Not every frame will always go through every part of the pipeline. In fact, whether using JavaScript, CSS, or web animation, when implementing visual changes, there are usually three ways that pipeline frames run on a given frame:

[The following screenshots are drawn with the timeline as the main axis]

file

- When modifying some properties that will trigger the layout, it will cause the subsequent ones to be updated as well.

file

  • When the modification only changes the properties of paint, it will not re-layout.

    file

  • If you change some data that does not involve layout or redrawing, you can directly perform composite rendering.

Like CSS properties, you can query this website to see which properties cause what kind of frame pipeline: https://csstriggers.com/

For example: transform transformation, it is a change that does not trigger layout and drawing, so when using it, it directly enters the third state, and after synthesis, directly enters the Composite stage, which is a good optimization method.

file

Question 3: The execution of requestAnimationFrame (rAF) is displayed on the console, so what does this rAF execution have to do with the browser frame? Let's look down.

2.2 requestAnimationFrame execution

We still run the code of demo1:

It can be seen that rAF is executed before layout and paint, and rAF is executed only once per frame, and the callback function is called to execute the animation.

From the execution timing of rAF, it can be seen that the execution timing of setTimeout is different from that of rAF.

By capturing the performance of the block moving animation in different ways, we can see:

  • Screenshot of setTimeout unit frame:
  • file
  • rAF unit frame screenshot:

file

Comparing the two, it can be seen that in the time of 16.7ms, seTimeout is executed 4 times, resulting in the difference between the marginLeft set at this time and the marginLeft before the last rendering is greater than 1px.

And raf can see that the difference between marginLeft and marginLeft before the last rendering is equal to 1px.

From the performance of rAf, it can be seen that the performance of setTimeout will be worse

Then, if the execution time of JS is too long, there is no drawing when one frame should be drawn, and the execution of the drawing is delayed until the next frame, which will cause the animation to freeze. [You can skip to the third part of the performance problem here, and you can see the Caton intuitively]

Thus it can be concluded that:

1.setTimeout time is inaccurate, because its execution depends on the execution time of the main thread.

2. If the timer frequency is higher than the browser refresh frequency, even if the code is executed and the browser is not refreshed, it will not be displayed, and the frame will be dropped, which is not smooth.

And raf solves the problem caused by setTimeout animation:

1. It is automatically executed when the browser refreshes the screen, and there is no need to set the time interval to be executed after n milliseconds like setTimeout, but this n milliseconds is automatically set to the browser refresh frequency. Once the browser refreshes, it is executed once, and no manual setting is required;
If the browser is not refreshed, it will not be executed, and there is no case of queuing and dropping frames.

2. High-frequency function throttling For resize and scroll high-frequency trigger events, using requestAnimationFrame can ensure that the function is executed only once in each drawing interval, saving the cost of function execution.
If you use setTimeout and setInterval, there may be useless callback function calls in the browser refresh interval, wasting resources.

Part 3 Performance Analysis and High-Performance Animations

3.1 Performance Analysis

Through chrome-performance, you can see the overall fps and GPU conditions, and you can also analyze the factors affecting the scripting\rendering\painting time frame by frame, so as to improve the performance of animation in a targeted manner.

demo3:
----- The up and down movement of the small square-----

The online address of the demo: https://googlechrome.github.io/devtools-samples/jank/

Source screenshot:

file

Not optimized [every block needs to force the layout to calculate the position]:

file

After clicking the Optimize button to optimize [read only once, and stored in the pos variable]:

file

Optimize again [add transform:translateZ(0), improve the level]:

file

The above is a small case of gradual optimization of animation: For specific operations, you can view the original text:
https://developer.chrome.com/docs/devtools/evaluate-performance/

3.2 How to optimize animation performance

According to the discussion of the rendering mechanism above, we can see that the factors affecting animation rendering are the various stages experienced by the frame pipeline, from which we can summarize some means to optimize animation performance:

  1. Improve performance every frame
  2. Avoid frequent rearrangements
  3. Avoid large repaints
  4. Optimize the performance of JS
  5. The fps is stable, avoiding frame dropping and frame skipping
  6. Not in continuous animation, add energy-intensive operations
  7. If you can't avoid it, you can do it at the beginning or end of the animation
  8. Enable GUP acceleration

The fourth part commonly used animation library

In summary, the implementation method can support some animation development, such as click interaction, carousel, and pure animation display, such as cash cows, fireworks, etc.

If strong interaction is required, or a gravity world is required, the implementation of native JS is relatively difficult. Some animation libraries can be used for development. These animations are implemented based on canvas and webGL.

  1. Pixi.js
  2. Add a scene
  3. add player
  4. Add own action
  5. add interaction
  6. phaser.js
    Physical system, gravity system can simulate falling state
  7. other:
    create.js, three.js 3d rendering, layaAir, Egret 3d game engine, etc., you can choose different frameworks to use according to the needs of different scenarios.

Summarize

  1. Implementation of animation

file

  1. Simple flow of browser rendering

file

  1. Develop the use of animation analysis performance reference performance

thanks

Many thanks to Mu Di and Qianxun for their corrections and suggestions on this article, and thanks to partners such as Liuyi and Shuangxu for their technical help and support in business products.


袋鼠云数栈UED
277 声望34 粉丝

我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。