欢迎关注我的公众号『 前端我废了 』,查看更多文章!!!
前言
在我们做一些数据可视化项目时,数字计数动画是一个很常见的需求,本文我们借助 countup.js 插件来实现效果,将它封装成一个 vue 3 组件,并扩展一些功能。
countup.js 介绍
countup.js
是一个可以快速创建各种有趣的数值动画效果的插件。例如可以自定义动画过渡函数,千分位符号,小数点位数,数值前后缀符号,数字符号替换等等。
它的构造函数有以下三个参数:
target
html 元素 id 或者 DOM 对象endVal
结束值options
其他可选配置项
constructor(target: string | HTMLElement | HTMLInputElement, endVal: number, options?: CountUpOptions)
它的 options 有以下可选配置项:
interface CountUpOptions {
startVal?: number // 开始数值,默认 0
decimalPlaces?: number // 小数点后位数,默认 0
duration?: number // 动画时长,默认 2s
prefix?: string // 数值前缀
suffix?: string // 数值后缀
// ...其他配置项
}
示例
const countup = new CountUp('targetId', 5234, options)
// 调用 start 方法开始计数
countup.start()
封装组件
我们抽出 countup.js
的以下属性作为我们组件 prop,其余的配置项通过 options
属性暴露出来供外部配置。
endVal
开始数值startVal
结束数值duration
动画时长,单位:秒
// 简略代码,完整代码可查看仓库
<script setup lang="ts">
defineProps<{
endVal: number | string
startVal?: number | string
duration?: number | string
options?: CountUpOptions
}>()
let elRef = ref<HTMLElement>()
onMounted(() => {
new CountUp()
})
</script>
使用组件
<count-up :end-val="2000"></count-up>
以上,就完成了对 countup.js 插件的简单封装。下面我们将在这基础上扩展一些功能。
扩展功能
我们想要给组件增加以下功能:
自动计数
:组件渲染后自动计数循环计数
:支持无限\有限次循环前后缀插槽
:满足自定义前后缀需求
1. 自动计数
countup.js 每次创建实例后需要我们手动调用 start()
方法来启动计数。我们给组件添加一个 autoplay
属性,来让组件渲染后默认自动计数。
// 简略代码,完整代码可查看仓库
<script setup lang="ts">
const props = defineProps({
autoplay: {
type: Boolean,
default: true
}
})
// 在 onMounted 判断一下就 ok 了
onMounted(() => {
if(props.autoplay) {
countup.start()
}
})
</script>
2. 循环计数
首先,定义一个循环函数 loopAnim
,
实现无限次循环:countup.js
的 start(callback)
方法支持传入一个回调函数,会在计数完成时执行,因此我们只需要在回调内继续调用 loopAnim()
函数就可以实现无限循环;
实现有限次循环:定义一个变量 loopCount
记录循环的次数,当小于我们定义的次数时,继续调用 loopAnim
。
// 简略代码,完整代码可查看仓库
<script setup lang="ts">
const props = defineProps({
// 支持传入布尔值或循环次数数值
loop: {
type: [Boolean, Number],
default: false
}
})
let loopCount = 0
const loopAnim = () => {
loopCount++
// 判断是否为布尔值且为 true
const isTruely = typeof props.loop === 'boolean'
&& props.loop
// 当为 true 或者已循环次数小于我们定义的次数时,继续循环计数
if(isTruely || props.loop > loopCount) {
countup.start(loopAnim)
}
}
onMounted(() => {
countup.start(loopAnim)
})
</script>
3. 前后缀插槽
当我们需要区分开前后缀与数字的样式时,可以通过插槽的形式实现,这个比较简单,只需要在组件 template 内定义两个具名插槽即可。
<template>
<div class="countup-wrap">
// 前缀插槽
<slot name="prefix"></slot>
// 数值显示位置
<span ref="elRef"> </span>
// 后缀插槽
<slot name="suffix"></slot>
</div>
</template>
总结
ok,到这里我们已经通过将 countup.js
封装为 vue 组件,实现满足了我们的需求,详细的代码实现可以查看我的 github 仓库。
我们后续可以把这个组件发布到 npm 上面,方便使用的同时也可以让更多人来使用你的组件,具体步骤可以自己看看其他文章怎么发布到 npm 上。
相关地址
npm
https://www.npmjs.com/package/vue-countup-v3
github
https://github.com/jizai1125/vue-countup-v3
在线 demo
https://jizai1125.github.io/vue-countup-v3/examples/