The principle of
- Window. RequestAnimationFrame can ensure implementation animation frequency 60 times per second (and sometimes also can appear the phenomenon of frequency reduction)
- Each change in the number counts as an animation
- Before performing each animation, the use of the window. The cancelAnimationFrame cancel animation, thus ensuring the browser performance
way
- Specify the time to complete the animation
- 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/