How to elegantly implement digital increment special effects in vue

need

A few days ago, I encountered a requirement in the project development, which needs to realize the effect of dynamic increment when the number is updated.

And, when the number is greater than 10,000 , convert the unit, such as when the number is greater than 10,000, the unit changes from m² to 10,000

Let's take the development in Vue as an example to realize these two requirements one by one.

accomplish

Basic development ideas

To achieve digital increment, the easiest way is to realize the digital accumulation function through the setinterval function. For example, if our final value is finanllyNum, we can quickly think of such a function:

let finalNum = 1200
let count = 0
let timer = setInterval(() => {
    
    
  count ++ 
  if(count > finalNum){
    
    
    // 避免count大于finalNum最终数字显示不对
    count = finalNum
    // 清空定时器
    clearInterval(timer)
    timer = null
  }
}, 10);

In this code, count is the number we want to display in the browser in real time. We increment the number every 10ms, so as to realize the dynamic increment effect of the number.

Development of instructions

Since many such function points are involved in the project, this function should be packaged and reused uniformly. Since we are using the vue technology stack, obviously, it is most appropriate to implement this function through instructions in vue .

The following implementation schemes are based on Vue instructions, so you need to refer to the official website to learn the basic usage of instructions in Vue.

The usage of vue2 and vue3 instructions is similar, this example demonstrates with vue2

Basic Structure of Instructions

First, we create the change.js file and write the most basic structure of the command

// js实现动态变化的数字
const directive = {
  inserted(el:any, binding:any) {
    ...
  },
};
export default directive

Introduce this file in main.js

import Vue from "vue";
import App from "./App.vue";
import directive from "./change";

Vue.config.productionTip = false;
// 注册名为 change 的指令
Vue.directive("change", directive);
new Vue({
  render: (h) => h(App),
}).$mount("#app");

At this point, we created a command called v-change , we directly use

// App.vue
<template>
  <div id="app">
    <span> 240 </span>
  </div>
</template>

Combined with our original implementation ideas, we can improve the instructions

// js实现动态变化的数字
const directive = {
    
    
  inserted(el, binding) {
    
    
  	// 获取到需要动态变化的数值
    let finalNum = el.innerText;
    let count = 0;
    let timer = setInterval(() => {
    
    
      count++;
      el.innerText = count;
      if (count > finalNum) {
    
    
        //  避免count大于finalNum最终数字显示不对
        count = finalNum;
        el.innerText = count;
        // 清空定时器
        clearInterval(timer);
        timer = null;
      }
    }, 10);
  },
};
export default directive;

Open the browser and you can see that our command is basically completed.

But there is a very big problem with this command at present. What we set is to increase the number every 10ms (number plus 1). If the number is very large, such as 12000 , wouldn't the dynamic change process of this number be very long?

We should make the number complete within the specified time no matter how big it is.

Optimization of instructions

In order for the numbers to change within a specified time, we need to find some mathematical relationships in the process of this change. At present, we already know that the initial value of the change is 0, the final value of the change is 12000, and the total duration of the animation (assumed to be 2S). Secondly, the interval duration of each frame of animation is also a value that we should consider.

In the example at the beginning, every 10ms is the interval of each frame of animation.

Simply understand, the animation interval is the frequency of animation changes per second

Let's understand it through two diagrams:

As shown in the figure, when the time interval is 166.7ms , the number changes 6 times in 1s , respectively 100, 200, 300, 400, 500, 600

When the time interval is 100ms , the number 1s changes 10 times, so it is 60, 120, 180, ..., 600

It can be seen that the smaller the time interval, the faster the number changes.

Now we can get such a mathematical relationship:

Total animation duration / time interval * digital step size (increased value per 1 time interval) = 1200

Now, we can optimize the instruction

// js实现动态变化的数字
const directive = {
    
    
  inserted(el, binding) {
    
    
    // 最终要显示的数字
    let finalNum = el.innerText;
    // 动画间隔
    let rate = 30;
    // 总时长
    let time = 2000;
    // 步长,数据增加间隔
    let step = finalNum / (time / rate);
    // 初始值
    let count = 0;
    // 要保留的小数
    let timer = setInterval(() => {
    
    
      count = count + step;
      el.innerText = count.toFixed(0);
      if (count > finalNum) {
    
    
        //  避免count大于finalNum最终数字显示不对
        count = finalNum;
        el.innerText = count;
        // 清空定时器
        clearInterval(timer);
        timer = null;
      }
    }, rate);
  },
};
export default directive;

The effect is very good!

Realize unit change

How can there be a unit behind the number, and how do we realize the change of the unit?

the first method:

Dynamically assign values ​​to numbers through js, this method is easy to understand

    let timer = setInterval(() => {
    
    
      count = count + step;
      // 根据不同数值显示不同单位
      if( count < 1000 ){
    
    
        el.innerText = count.toFixed(0) + "个"
      }else{
    
    
        el.innerText = (count / 1000 ).toFixed(0) + "千个"
      }
      if (count > finalNum) {
    
    
        count = finalNum;
        //  避免count大于finalNum最终数字显示不对
        if( count < 1000 ){
    
    
          el.innerText = count.toFixed(0) + "个"
        }else{
    
    
          el.innerText = (count / 1000 ).toFixed(0) + "千个"
        }
        // 清空定时器
        clearInterval(timer);
        timer = null;
      }
    }, rate);

This method has a big flaw, that is, the unit must be hardcoded in the instruction, as shown in the figure below, what should we do if we want to realize many dynamic numbers and need different units?

The second method:

Commands can pass parameters

<template>
  <div id="app">
    <div >
      <span v-change="{eUnit:'个',eUnit:'万个'}"> 1200 </span>
    </div>
  </div>
</template>

Parameters can be accepted via binding.value . We can process the logic through the obtained parameters, as follows:

// js实现动态变化的数字
const directive = {
    
    
  inserted(el, binding) {
    
    
    // .....
    let timer = setInterval(() => {
    
    
      count = count + step;
      if( count < 1000 ){
    
    
        // binding.value.bUnit是我们通过指令传递进来的参数
        el.innerText = count.toFixed(0) +  binding.value.bUnit
      }else{
    
    
        el.innerText = (count / 1000 ).toFixed(0) + binding.value.eUnit
      }
      if (count > finalNum) {
    
    
      //  避免count大于finalNum最终数字显示不对
        count = finalNum;
        if( count < 1000 ){
    
    
          el.innerText = count.toFixed(0) + binding.value.bUnit
        }else{
    
    
          el.innerText = (count / 1000 ).toFixed(0) + binding.value.eUnit
        }
        // 清空定时器
        clearInterval(timer);
        timer = null;
      }
    }, rate);
  },
};
export default directive;

Of course, there are other implementation logics, and everyone is welcome to use their strengths! If you need the complete source code, please contact me.

Guess you like

Origin blog.csdn.net/weixin_46769087/article/details/128286235