vue中优雅实现数字递增特效的详细过程

目录
  • 需求
  • 实现
    • 基本开发思路
    • 指令的开发
      • 指令的基本结构
    • 指令的优化
      • 实现单位变化
  • 总结

需求

前几天项目开发中遇到一个需求,需要在数字更新时,实现其动态递增的效果

并且,在数字大于10000时,将单位进行转换,如数字大于10000时,单位从变为万

我们以vue中开发为例,一一实现下这两个需求。

实现

基本开发思路

实现数字递增,最容易的,我们应该可以想到通过setinterval函数实现数字累加功能。比如,我们的最终值是finanllyNum, 我们可以很快想到这样的函数:

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

这个代码中,count是我们要实时在浏览器中显示的数字。我们每10ms实现数字进行一次递增,从而实现数字的动态递增特效。

指令的开发

由于项目中涉及很多这样的功能点,因此,这个功能应该被统一进行封装和复用。由于我们使用的是vue技术栈,显然,通过vue中的指令来实现这个功能最合适。

以下实现方案基于vue指令实现,因此,您需要参考官网了解学习vue中指令的基本用法。

vue2和vue3指令的用法大同小异,本示例以vue2进行演示

指令的基本结构

首先,我们创建change.js文件,写入指令的最基本结构

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

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");

此时,我们创造了一个名为v-change的指令,我们直接使用

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

结合我们最开始的实现思路,可以完善指令

// 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;

打开浏览器,可以看到我们的指令基本完成了。

但目前这个指令有个非常大的问题。我们设置的是每10ms增加一下数字(数字加1),如果数字非常大比如为12000,那么这个数字的动态变化过程岂不是非常长?

我们应该让数字无论多大,都在指定时间完成才行。

指令的优化

要想数字在指定时间完成变化,我们需要找到这个变化过程中的一些数学关系。目前,我们已经知道的有变化初始值0,变化最终值12000,动画总时长(假设为2S)。其次,每帧动画的间隔时长也是我们应该考虑的一个数值。

一开始的示例中,每10ms就是每帧动画的间隔时长。

简单理解,动画的间隔时长就是每秒动画变化的频率

我们通过两个图来理解一下:

如图,时间间隔为 166.7ms时,数字1s变化6次,分别为 100,200,300,400,500,600

当时间间隔为 100ms时,数字1s变化10次,以此为60,120,180,.......,600

可见,时间间隔越小,数字变化的也就越快。

现在我们可以得到这样一个数学关系:

动画总时长 / 时间间隔 * 数字的步长(每 1时间间隔增加的值) = 1200

现在,我们可以优化一下指令了

// 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;

效果非常不错!

实现单位变化

如何数字后面有单位,我们要怎么实现单位的变化呢?

第一种方法:

通过js动态为数字后赋值,这种方法很好理解

    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);

这个方法有一个很大的缺陷,就是单位必须写死在指令里,如下图,如果我们要实现很多动态数字而且需要不同单位该怎么办呢?

第二种方法:

指令是可以传递参数的

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

通过binding.value可以接受参数。我们可以通过获取的参数,来处理逻辑,如下:

// 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;

当然,还有其他实现逻辑,也欢迎大家发挥自己的所长!

总结

到此这篇关于vue中优雅实现数字递增特效的文章就介绍到这了,更多相关vue数字递增特效内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue 实现数字滚动增加效果的实例代码

    项目中需要做数字滚动增加的效果,一开始很懵,研究了一下原理,发现很简单,贴出来分享一下 ^_^ 数字滚动组件: <template> <div class="number-grow-warp"> <span ref="numberGrow" :data-time="time" class="number-grow" :data-value="value">0</sp

  • vue中优雅实现数字递增特效的详细过程

    目录 需求 实现 基本开发思路 指令的开发 指令的基本结构 指令的优化 实现单位变化 总结 需求 前几天项目开发中遇到一个需求,需要在数字更新时,实现其动态递增的效果 并且,在数字大于10000时,将单位进行转换,如数字大于10000时,单位从m²变为万m² 我们以vue中开发为例,一一实现下这两个需求. 实现 基本开发思路 实现数字递增,最容易的,我们应该可以想到通过setinterval函数实现数字累加功能.比如,我们的最终值是finanllyNum, 我们可以很快想到这样的函数: let

  • vue中npm包全局安装和局部安装过程

    全局安装是将npm包安装在你的node安装目录下的node_modules文件夹中.在windows和mac中,全局安装的默认路径是不同的.在mac中默认是安装到 /usr/locla/lib 中.在windows默认安装目录是 C:\Program Files\nodejs ,当然你也可以通过一下命令来查看全局安装路径. // 查看全局安装路径 npm root -g // 查看npm的基础设置 npm config ls // 查看安装目录路径 npm config get prefix 全

  • C++中opencv4.1.0环境配置的详细过程

    准备 Open CV 的文件 : https://opencv.org/releases/ 解压到哪里无所谓,我们后面会把需要的文件复制到 Solution 的目录里面.我本机解压到F:\opencv4.1.0 新建Open CV 的测试工程: 新建一空白的C++工程,设为opencv_test 工程设置为Debug的x64模式 右键单击工程->属性,打开配置的属性页 在VC++目录中添加包含目录: F:\opencv4.1.0\build\include;F:\opencv4.1.0\buil

  • js实现数字递增特效【仿支付宝我的财富】

    上周五应着公司临时需求,一天的时间解决掉官网(ps:比较简单哈哈),需求里面有一个特效就是数字递增到指定的数值,其实JS写也不复杂的,但是我发现一个js小插件,这个插件轻巧简单,用起来也非常简单实用.在这里分享给小盆友们吧,喜欢的直接拿走. 上面就是这个插件的效果,我们来看一下怎么使用的吧 第一: HTML部分这里简单列举一个 <div class="counter col_fourth"> <h2 class="timer count-title"

  • vue中使用svg画路径图的详细介绍

    什么是svg: SVG 是使用 XML 来描述二维图形和绘图程序的语言. svg的优点与特点 SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失 SVG 是万维网联盟的标准 SVG 与诸如 DOM 和XSL 之类的 W3C 标准是一个整体 SVG 可被非常多的工具读取和修改(比如记事本) SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强. SVG 是可伸缩的 SVG 图像可在任何的分辨率下被高质量地打印 SVG 可在图像质量不下降的情况下被放大 SVG 图像中的文本

  • Vue中通过minio上传文件的详细步骤

    目录 1.minio的安装 2.minio.js文件 2.1连接minio 2.2通过stream流上传 2.3通过带预签名的url上传(最好是minio设置了链接永久访问) 2.4删除对象 补充:base64转blob 3.获取时间方法 4.minio设置链接永久访问(客户端) 5.解决跨域问题 6.存储大小限制问题 7.minio官方文档 8.minio设置链接永久访问(其他方法) 总结 在Vue中minio上传文件(stream流和链接) 1.minio的安装 直接使用npm或者cnpm下

  • vue中实现拖拽排序功能的详细教程

    目录 原生拖拽 API 实现拖拽 设置元素 dragable 拖放事件 拖拽排序 拖拽API + 防抖实现 vue awe-dnd 拖拽组件 安装 awe-dnd 组件库 在 main.js 中将 awe 挂载到全局 实现案例 项目中-- 拖拽的效果 不理想 vue-smooth-DnD 安装 smooth-dnd API: container smooth-dnd 生命周期 回调 事件 API: Draggable 效果实现 项目中实现 – 拖拽位置无法确定 vuedraggable 安装 引

  • windows下在vim中搭建c语言开发环境的详细过程

    1 代码格式化 C语言代码的格式化需要使用clang-format,而clang-format被集成在了llvm中,所以需要先安装llvm,点击此处下载 下载之后运行安装文件,将其中的bin目录添加到环境变量path中(需重启电脑使新添加的环境变量生效).例如我安装后的目录为C:\wsr\LLVM\bin,图中的clang-format就是格式化c代码需要的组件 1.1 clang-format初体验 test1.c #include <stdio.h> int main(int argc,

  • Python Scala中使用def语句定义方法的详细过程

    Scala和Java一样也有方法和函数.Scala的方法是类的一部分,而函数是一个对象可以赋值给一个变量.换句话来说,在类中定义的函数即是方法.Scala中可以使用df语句和val语句定义函数,而定义方法只能使用def语句.下面来讲解Scala的方法. Scala方法的定义格式如下: 从上面的代码可以看出,Scala的方法是由多个部分组成的,具体如下. def functionName([参数列表]):[return type]={ function body return [expr] } ·

  • 如何在vue中使用kindeditor富文本编辑器

    第一步,下载依赖 yarn add kindeditor 第二步,建立kindeditor.vue组件 <template> <div class="kindeditor"> <textarea :id="id" name="content" v-model="outContent"></textarea> </div> </template> <s

随机推荐