JS timer mechanism and front-end animation from n implementations of typewriter effect

Time:2021-9-26

First, what is the typewriter effect? Typewriter effect is to output text one by one, which is actually a kind of Web animation. A picture is worth a thousand words. Please see:

JS timer mechanism and front-end animation from n implementations of typewriter effect

In web applications, there are many ways to realize animation effects. In JavaScript, it can be realized by timer setTimeout, CSS3 can be realized by transition and animation, and canvas in HTML5 can also be realized. In addition, HTML5 also provides an API specifically for requesting animation, that is, request animation frame (RAF), which is “request animation frame” as its name implies. Next, let’s look at several implementations of typewriter effects. In order to facilitate understanding, I will try to implement it in a concise way. If you are interested, you can also transform these implementations into more compelling and artistic, because programming is an art.

N implementations of typewriter effect

Implementation 1: setTimeout ()

   the implementation of setTimeout version is very simple, justCut the text to be displayed and use the timer to continuously add text to the DOM elementAt the same time, use:: after pseudo elementThe cursor flickers behind the DOM element. The code and effect diagram are as follows:

<!--  Style -- >
<style type="text/css">
  /*Set container style*/
  #content {
    height: 400px;
    padding: 10px;
    font-size: 28px;
    border-radius: 20px;
    background-color: antiquewhite;
  }
  /*Produces the effect of flashing the cursor*/
  #content::after{
      content: '|';
      color:darkgray;
      animation: blink 1s infinite;
  }
  @keyframes blink{
      from{
          opacity: 0;
      }
      to{
          opacity: 1;
      }
  }
</style>

<body>
  <div id='content'></div>
  <script>
    (function () {
    //Get container
    const container = document.getElementById('content')
    //Cut all the words to be displayed
    Const data = 'simplest typewriter effect implementation'. Split ('')
    //The text subscript that needs to be appended to the container
    let index = 0
    function writing() {
      if (index < data.length) {
        //Append text
        container.innerHTML += data[index ++]
        let timer = setTimeout(writing, 200)
        Console.log (timer) // 1 2 3 4 5 6 7 8 9 10 will be printed here in turn
      }
    }
    writing()
  })();
  </script>
</body>

JS timer mechanism and front-end animation from n implementations of typewriter effect

The return value of   settimeout() method is a unique value (ID). In the above code, we also print the return value of settimeout(). What is the use of this value?
    if you want to terminate the execution of the setTimeout () method, you must use the cleartimeout () method to terminate. When using this method, the system must know which setTimeout () method you want to terminate (because you may call several setTimeout () methods at the same time), so the cleartimeout () method needs a parameter, This parameter is the return value (value) of the setTimeout () method, which is used to uniquely determine which setTimeout () method to end.

Implementation 2: setinterval ()

The typewriter effect achieved by setinterval is actuallyMDN window.setinterval case 3There is already one in, and the control of playback, pause and termination is also realized. The effect can be clickedhereSee, here is only the simplest implementation of setinterval typewriter effect. In fact, the code is similar to the implementation of setTimeout above, and the effect is the same.

(function () {
  //Get container
  const container = document.getElementById('content')
  //Cut all the words to be displayed
  Const data = 'simplest typewriter effect implementation'. Split ('')
  //The text subscript that needs to be appended to the container
  let index = 0
  let timer = null
  function writing() {
    if (index < data.length) {
      //Append text
      container.innerHTML += data[index ++]
      //Yes, you can also cancel the execution of setinterval through cleartimeout
      // index === 4 && clearTimeout(timer)
    } else {
      clearInterval(timer)
    }
    Console.log (timer) // 1 will be printed here
  }
  //When using setinterval, don't forget to perform clearinterval after the end
  timer = setInterval(writing, 200)
})();

   like setTimeout, setinterval will also return an ID (number), which can bePass this ID to clearinterval () or cleartimeout () to cancel the execution of the timer

  it is necessary to emphasize here:The time interval specified by the timer, which indicates when the timer’s code is added to the message queue, rather than when the code is executed.Therefore, the real time when the code is executed cannot be guaranteed, depending on when it is fetched and executed by the event loop of the main thread.

Implementation 3: requestanimationframe()

In the implementation of animation, requestanimationframe undoubtedly has more advantages than setTimeout and setinterval. Let’s first look at the requestanimationframe implementation of the typewriter effect:

(function () {
    const container = document.getElementById('content')
    Const data = 'compared with setTimeout, the biggest advantage of requestanimationframe is that the system determines the execution time of the callback function. Specifically, the system will actively call the callback function in requestanimationframe before each drawing. If the system drawing rate is 60Hz, the callback function will be executed every 16.7ms. If the drawing frequency is 75Hz, the interval will become 1000 / 75 = 13.3ms. In other words, the execution pace of requestanimationframe follows the drawing frequency of the system. It can ensure that the callback function is executed only once in each drawing interval of the screen, so as not to cause frame loss and jam in the animation split('')
    let index = 0
    function writing() {
      if (index < data.length) {
        container.innerHTML += data[index ++]
        requestAnimationFrame(writing)
      }
    }
    writing()
  })();

JS timer mechanism and front-end animation from n implementations of typewriter effect

  compared with setTimeout, the biggest advantage of requestanimationframe isThe execution timing of the callback function is determined by the system。 Specifically, if the screen refresh rate is 60Hz, the callback function is executed every 16.7ms. If the refresh rate is 75Hz, the time interval becomes 1000 / 75 = 13.3ms. In other words, the pace of requestanimationframe follows the pace of system refresh.It can ensure that the callback function is executed only once in each refresh interval of the screen, so that it will not cause frame loss and jam in the animation

Implementation 4: CSS3

  in addition to the above three JS methods, we can also achieve typewriter effect only with CSS. The general idea is to use CSS3@keyframesTo constantly change the width of the container containing text, and the text beyond the container is hidden and not displayed.

<style>
  div {
    font-size: 20px;
    /*The initial width is 0*/
    width: 0;
    height: 30px;
    border-right: 1px solid darkgray;
    /*
    Steps(<number_of_steps>,<direction>)
    Steps receives two parameters: the first parameter specifies the number of segments divided by the animation; The second parameter is optional. It accepts the values of start and end, and specifies the step change at the start or end of each interval. The default is end.
    */
    animation: write 4s steps(14) forwards,
      blink 0.5s steps(1) infinite;
      overflow: hidden;
  }

  @keyframes write {
    0% {
      width: 0;
    }

    100% {
      width: 280px;
    }
  }

  @keyframes blink {
    50% {
      /*Transparent is a shorthand for fully transparent black, that is, a value similar to RGBA (0,0,0,0)*/
      border-color: transparent; /* #00000000 */
    }
  }
</style>

<body>
  <div>
    The great river goes East and the waves wash away. It is a romantic figure through the ages
  </div>
</body>

JS timer mechanism and front-end animation from n implementations of typewriter effect

The principle of the above CSS typewriter effect is clear at a glance:

  • The initial text is all on the page, but the width of the container is 0. Set the excess part of the text to be hidden, and then constantly change the width of the container;
  • set upborder-right, and change on keyframesborder-colorbytransparent, the right border is like a flashing cursor.

Implementation 5: typed.js

Typed.js is a library that types. Enter in any string, and watch it type at the speed you’ve set, backspace what it’s typed, and begin a new sentence for however many strings you’ve set.

  typed.js is a lightweight typing animation library. It only needs a few lines of code to realize the cool typewriter effect in the project (the first moving picture in this paper is the implementation of typed.js). The source code is also relatively simple. If you are interested, you can go toGitHub for study

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script></script>
</head>

<body>
  <div id="typed-strings">
    <p>Typed.js is a <strong>JavaScript</strong> library.</p>
    <p>It <em>types</em> out sentences.</p>
  </div>
  <span id="typed"></span>
</body>
<script>
  var typed = new Typed('#typed', {
    stringsElement: '#typed-strings',
    typeSpeed: 60
  });
</script>

</html>

JS timer mechanism and front-end animation from n implementations of typewriter effect

Using typed.js, we can also easily control the start and pause of animation:

<body>
  <input type="text" class="content" name="" style="width: 80%;">
  <br>
  <br>
  < button class = "start" > start < / button >
  < button class = "stop" > pause < / button >
  < button class = "toggle" > toggle < / button >
  < button class = "reset" > Reset < / button >
</body>
<script>
const startBtn = document.querySelector('.start');
const stopBtn = document.querySelector('.stop');
const toggleBtn = document.querySelector('.toggle');
const resetBtn = document.querySelector('.reset');
const typed = new Typed('.content',{
  Strings: ['after the rain in the egret state, I miss the Tongque building. The setting sun dyed the secluded grass. It flew red several times, swaying the far sail on the river. Looking back at the lamp like a flower, people are ashamed before they speak.'],
  typeSpeed: 200,
  startDelay: 100,
  loop: true,
  loopCount: Infinity,
  bindInputFocusEvents:true
});
startBtn.onclick = function () {
  typed.start();
}
stopBtn.onclick = function () {
  typed.stop();
}
toggleBtn.onclick = function () {
  typed.toggle();
}
resetBtn.onclick = function () {
  typed.reset();
}
</script>

JS timer mechanism and front-end animation from n implementations of typewriter effect

reference material:Typed.js official website | Typed.js GitHub address

Of course, the implementation method of typewriter effect is not limited to the above methods. The purpose of this paper is not to search for the implementation of all typewriter effects. If so, it will be meaningless. Next, we will compare CSS3 animation with JS animation, and summarize some details of setTimeout, setinterval and requestanimationframe.

Comparison between CSS3 animation and JS animation

  about CSS animation and JS animation,There is a saying that CSS animation is smoother than JS. In fact, this fluency has a premise。 Take this opportunity to make a simple comparison between CSS3 animation and JS animation.

JS animation

  • advantage:

    • JS has strong animation control ability, and can finely control the animation during animation playback, such as start, pause, termination, cancellation, etc;
    • JS animation effect is richer than CSS3 animation and has a wide range of functions, such as curve motion, impact flicker, parallax scrolling and other effects that are difficult to achieve by CSS;
    • JS animation has no compatibility problem in most cases, while CSS3 animation has compatibility problem;
  • Disadvantages:

    • JS runs in the main thread of the browser, and there are other JS scripts, style calculation, layout, drawing tasks that need to be run in the main thread. Interference with it may lead to thread blocking and frame loss;
    • For low version browsers with poor frame rate performance, CSS3 can be degraded naturally, while JS needs to write additional code;
    • JS animation often needs to frequently operate the CSS attribute of DOM to achieve visual animation effect. At this time, the browser keeps performing redrawing and rearrangement, which consumes a lot of performance, especially on the mobile terminal with less abundant memory allocated to the browser.

CSS3 animation

  • advantage:

    • In some cases, the browser can optimize the animation (for example, create a new layer to run the animation). Why do you say that in some cases, because it is conditional:

      • In chrome based browsers
      • At the same time, CSS animation does not trigger layout or paint. When CSS animation or JS animation triggers paint or layout, main thread is required to recalculate the layer tree. At this time, CSS animation or JS animation will block subsequent operations.
    • Some effects can force the use of hardware acceleration (improve animation performance through GPU)
  • Disadvantages:

    • The code is lengthy. CSS implementation is a little more complex, and CSS code may become very cumbersome;
    • Weak operation process control. CSS3 animation can only control the pause and continuation of animation in some scenes, and callback functions cannot be added at specific positions.

Main thread and composition thread

  • Rendering threads are divided into main thread and composition thread.In the main thread, a layer tree (layertreehost) is maintained and tiledlayer is managed. In the composition thread, the same layertreehostimpl is maintained and layerimpl is managed. The contents of these two trees are copy relationship. Therefore, they can not interfere with each other. When JavaScript operates layertreehost in the main thread, the composition thread can be rendered with layertreehostimpl. When JavaScript is busy and the main thread gets stuck, the process of synthesizing to the screen is also smooth.
  • In order to prevent fake death, the mouse and keyboard messages will be distributed to the composite thread first, and then to the main thread. In this way, when the main thread is busy, the composition thread can still respond to some messages. For example, when the mouse scrolls, if the main thread is busy, the composition thread will also process the scrolling message and scroll the submitted page part (the uncommitted part will be whitewashed).

CSS animation is more fluent than JS animation

  • CSS animation is less or does not trigger pain and layout, that is, when redrawing and rearrangement. For example, by changing the CSS animation generated by the following attributes, the whole CSS animation can be completed in the composition thread (while the JS animation will be executed in the main thread, and then trigger the composition for the next operation):

    • Backface visibility: this attribute specifies whether the element is visible when its back faces the observer (3D, function in the experiment);
    • Opacity: sets the opacity level of div elements;
    • Perspective sets the element view, which only affects 3D conversion elements;
    • Perspective origin: this attribute allows you to change the bottom position of 3D elements;
    • Transform: this attribute is applied to the 2D or 3D transformation of the element. This property allows you to rotate, scale, move, tilt, and so on.
  • When JS performs some expensive tasks, the main thread is busy, and CSS animation can remain smooth due to the use of composite thread;
  • Some attributes can start 3D acceleration and GPU hardware acceleration, for example, when using the translatez of transform for 3D transformation;
  • By settingwill-changeAttribute, the browser can know which element attributes will change in advance and prepare in advance. When the time comes to change elements, they can be implemented immediately, so as to avoid problems such as Caton.

    • Don’t putwill-changeIf it is applied to too many elements, it may lead to slow page response or consume too many resources.
    • For example, the following code tells the rendering engine in advance that the box element will undergo geometric transformation and transparency transformation. At this timeThe rendering engine implements the element in a single frame, when these transformations occur, the rendering engine will directly process the transformations through the synthesis thread. These transformations do not involve the main thread, which greatly improves the efficiency of rendering.

      .box {will-change: transform, opacity;}

Some details of setTimeout, setinterval and requestanimationframe

SetTimeout and setinterval

  • The execution time of setTimeout is not certain. In JavaScript, the setTimeout task is put into an asynchronous queue,Only after the tasks on the main thread are executed, will you check whether the tasks in the queue need to be executedTherefore, the actual execution time of setTimeout is generally later than its set time.
  • The refresh rate is affected by the screen resolution and screen size. The screen drawing frequency of different devices may be different, and setTimeout can only set a fixed time interval, which is not necessarily the same as the screen refresh time.
  • The execution of setTimeout only changes the element attributes in memory. This change will not be updated to the screen until the next drawing of the screen. If the steps of the two are inconsistent, the operation of one frame in the middle may be crossed over and the elements of the next frame may be updated directly.Assuming that the screen is refreshed every 16.7ms and setTimeout sets the image to move 1px to the left every 10ms, the following drawing process will appear:

    • 0 ms: the screen is not drawn, waiting, setTimeout is not executed, waiting;
    • The 10th MS: the screen is not drawn, waiting, setTimeout starts to execute and sets the element attribute left = 1px;
    • 16.7 MS: the screen starts drawing, the elements on the screen move 1px to the left, setTimeout is not executed, and continue to wait;
    • The 20th MS: the screen is not drawn, waiting, setTimeout starts to execute and set left = 2px;
    • The 30th MS: the screen is not drawn, waiting, setTimeout starts to execute and set left = 3px;
    • 33.4 MS: the screen starts drawing, the elements on the screen move 3px to the left, setTimeout is not executed, and continue to wait;

   it can be seen from the above drawing process that the screen does not update the frame of left = 2px, and the elements directly jump from the position of left = 1px to the position of left = 3px, which isFrame loss phenomenon, this phenomenon will cause animation Caton.

  • The actual delay between the callback function calls of setinterval is less than the delay set in the code, because the time required for the execution of the callback function “consumes” part of the interval,If the callback function takes a long time and executes many times, the error will be larger and larger
// repeat with the interval of 2 seconds
let timerId = setInterval(() => console.log('tick', timerId), 2000);
// after 50 seconds stop
setTimeout(() => {
  clearInterval(timerId);
  console.log('stop', timerId);
}, 50000);

JS timer mechanism and front-end animation from n implementations of typewriter effect

  • Nested settimeouts guarantee a fixed delay:
let timerId = setTimeout(function tick() {
  console.log('tick', timerId);
  timerId = setTimeout(tick, 2000); // (*)
}, 2000);

JS timer mechanism and front-end animation from n implementations of typewriter effect

requestAnimationFrame

In addition to the advantages of requestanimationframe mentioned above, requestanimationframe has the following two advantages:

  • CPU energy saving: for the animation implemented by setTimeout, when the page is hidden or minimized, setTimeout still performs the animation task in the background. Because the page is invisible or unavailable at this time, refreshing the animation is meaningless and a complete waste of CPU resources. The requestanimationframe is completely different,When the page is inactive, the screen refresh task of the page will also be suspended by the system, so the requestanimationframe following the system will also stop rendering, when the page is activated, the animation will continue to execute from the last place, which effectively saves CPU overhead.
  • Function throttling: in high frequency events (resize, scroll, etc.), in order to prevent multiple function executions within a refresh interval, use requestanimationframe toEnsure that the function is executed only once in each refresh intervalThis can not only ensure the fluency, but also better save the cost of function execution. It is meaningless to execute the function multiple times within a refresh interval, because the display is refreshed every 16.7ms, and multiple drawings will not be reflected on the screen.

About minimum time interval

  • 2011 standardsIt is stipulated in:

    • SetTimeout: if the currently running task is a task created by the setTimeout () method and the time interval is less than 4ms, increase the time interval to 4ms;
    • Setinterval: if the time interval is less than 10ms, increase the time interval to 10ms.
  • In the latest standard: if the time interval is less than 0, set the time interval to 0. IfIf the nesting level is greater than 5 and the time interval is less than 4ms, set the time interval to 4ms.

Timer clear

  • Since cleartimeout() and clearinterval() clear entries in the same list (list of active timers), you can use both methods to clear timers created by settimeout() or setinterval().

reference material

Previous high score collection:

This article was first published inPersonal blog, welcomeCorrection and star

Recommended Today

Supervisor

Supervisor [note] Supervisor – H view supervisor command help Supervisorctl – H view supervisorctl command help Supervisorctl help view the action command of supervisorctl Supervisorctl help any action to view the use of this action 1. Introduction Supervisor is a process control system. Generally speaking, it can monitor your process. If the process exits abnormally, […]