The principle of

  1. Window. RequestAnimationFrame can ensure implementation animation frequency 60 times per second (and sometimes also can appear the phenomenon of frequency reduction)
  2. Each change in the number counts as an animation
  3. Before performing each animation, the use of the window. The cancelAnimationFrame cancel animation, thus ensuring the browser performance

way

  1. Specify the time to complete the animation
  2. Completes the animation at specified speed

Note: Currently the two methods are mutually exclusive

The core code

// count.js
/** * Two ways to support digital cumulative scrolling: * 1. Specify the speed, interval control, that is, control the interval between frames * 2. Specify the time, that is: No matter how big the number is, * @param {Object} option configuration * @param {Number} option.start Start Number * @param {Number} option.end Number * @param {Number} option.interval Specifies the interval between frames (ms) * @param {Boolean} option.limitTime Specifies the time * @param {Function} option.callback, The parameter is the cumulative number */

export default function Count({
    start = 0,
    end = 100,
    interval = 0,
    limitTime = 0,
    callback
}) {
    // Time per frame (ms)
    // According to MDN, it is usually 60 frames per second
    const frameTime = 1000 / 60;

    / / frames
    let frameAmount;

    / / step length
    // The cumulative value of each time. The default value is 1
    let frameStep = 1;

    / / counter
    // The counter takes effect only when interval is specified
    // Function: Used to compare with interval. When interval is equal to, the callback is executed, and then zero is cleared and the count is reset to control the speed
    let counter = 0;

    // If limitTime is specified, the step size is recalculated
    if(limitTime && ! interval) {let length = end - start;

        // Specify how many frames can be completed in that time
        frameAmount = limitTime / frameTime;

        // Take the minimum between the number of frames and the actual length
        if (frameAmount > length) {
            frameAmount = length;
        }

        frameStep = Math.round((end - start) / frameAmount);
    }

    // Frame callback function
    function step() {
        let req;

        // The common logic part of modes 1 and 2
        function commonLogic() {
            start += frameStep;
                
            // Prevent the number from jumping out of bounds during the last accumulation
            if (start >= end) {
                callback(end);
            } else {
                callback(start);
                window.cancelAnimationFrame(req);
                req = window.requestAnimationFrame(step); }}// Method 1: by time interval
        if(interval ! = =0) {
            counter++;

            if (counter === interval) {
                commonLogic();
                counter = 0;
            } else {
                window.cancelAnimationFrame(req);
                req = window.requestAnimationFrame(step);
            }
        // Method 2: the specified time
        } else {
            if(start < end) { commonLogic(); }}}window.requestAnimationFrame(step);
}
Copy the code

Example 1: Complete dynamic effects within a specified time

Note: combined with Vue implementation

<template> <div id="app"> <div>{{num}}</div> </div> </template> <script> import Count from './count'; Export default {name: 'app', data () {return {num: 0}}, mounted () {end: 100, // End time limitTime: Callback: (num) => {this.num = num; } }) } } </script>Copy the code

The results

Example 2: Complete dynamic effects at the specified speed

Note: combined with Vue implementation

<template> <div id="app"> <div>{{num}}</div> </div> </template> <script> import Count from './count'; Export default {name: 'app', data () {return {num: 0}}, Mounted () {Count({end: 100, // End: 100) Callback: (num) => {this.num = num; }}}})Copy the code

The results

The original link: https://www.guoyunfeng.com/2018/05/31/number-counter/