这篇“Vue3基于countUp.js如何实现数字滚动的插件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue3基于countUp.js如何实现数字滚动的插件”文章吧。
countUp 简介
CountUp.js 是一种无依赖项的轻量级 JavaScript 类,可用于快速创建以更有趣的方式显示数字数据的动画。CountUp 可以在两个方向上进行计数,具体取决于传递的开始和结束值。
虽然现在市面上基于 countUp.js 二次封装的Vue组件不在少数, 但我个人是不太喜欢使用这些第三方封装的,因为第三方组件的更新频率很难保证,也许作者只是一时兴起封装上传了, 并未打算继续维护,如果使用了 等于后续根本没有维护性了, 所以这种二次封装我推荐自行实现, 我们可以通过本次封装熟悉一下
vue3
, ts
的语法countUp 组件封装
首先进行安装
npm i countup.js
安装好之后新建文件
CountUp.vue
, template部分很简单, 只需要一个span
标签, 同时给span
一个 ref='countupRef'
就完成了,首先引入 countup.js
, 按住Ctrl鼠标左键点击Countup.js可以看到 d.ts文件, countUp.d.ts
如下export interface CountUpOptions {
startVal?: number;
decimalPlaces?: number;
duration?: number;
useGrouping?: boolean;
useIndianSeparators?: boolean;
useEasing?: boolean;
smartEasingThreshold?: number;
smartEasingAmount?: number;
separator?: string;
decimal?: string;
easingFn?: (t: number, b: number, c: number, d: number) => number;
formattingFn?: (n: number) => string;
prefix?: string;
suffix?: string;
numerals?: string[];
enableScrollSpy?: boolean;
scrollSpyDelay?: number;
scrollSpyOnce?: boolean;
onCompleteCallback?: () => any;
plugin?: CountUpPlugin;
}
export declare interface CountUpPlugin {
render(elem: HTMLElement, formatted: string): void;
}
export declare class CountUp {
private endVal;
options?: CountUpOptions;
version: string;
private defaults;
private rAF;
private startTime;
private remaining;
private finalEndVal;
private useEasing;
private countDown;
el: HTMLElement | HTMLInputElement;
formattingFn: (num: number) => string;
easingFn?: (t: number, b: number, c: number, d: number) => number;
error: string;
startVal: number;
duration: number;
paused: boolean;
frameVal: number;
once: boolean;
constructor(target: string | HTMLElement | HTMLInputElement, endVal: number, options?: CountUpOptions);
handleScroll(self: CountUp): void;
/**
* Smart easing works by breaking the animation into 2 parts, the second part being the
* smartEasingAmount and first part being the total amount minus the smartEasingAmount. It works
* by disabling easing for the first part and enabling it on the second part. It is used if
* usingEasing is true and the total animation amount exceeds the smartEasingThreshold.
*/
private determineDirectionAndSmartEasing;
start(callback?: (args?: any) => any): void;
pauseResume(): void;
reset(): void;
update(newEndVal: string | number): void;
count: (timestamp: number) => void;
printValue(val: number): void;
ensureNumber(n: any): boolean;
validateValue(value: string | number): number;
private resetDuration;
formatNumber: (num: number) => string;
easeOutExpo: (t: number, b: number, c: number, d: number) => number;
}
这里 export 了一个
CountUp
类 还有一个 CountUpOptions
的interface, CountUp
类的 constructor
接收三个参数, 分别是 dom节点, endVal, 以及 options, 我们将这三个参数当成是 props
传入同时给定默认值, , 首先获取span的ref作为 countUp
初始化的容器 , 定义一个变量 numAnim
接收 new CountUp(countupRef.value, props.end, props.options)
的返回值, , 在 onMounted
中初始化countUp.js
,接着我们就可以去页面引入 CountUp.vue
看看效果,因为有默认值,所以我们不需要传入任何参数, 直接看就好了, 此时CountUp.vue
组件代码如下,<script setup lang="ts">
import { CountUp } from 'countup.js'
import type { CountUpOptions } from 'countup.js'
import { onMounted, ref } from 'vue'
let numAnim = ref(null) as any
const countupRef = ref()
const props = defineProps({
end: {
type: Number,
default: 2023
},
options: {
type: Object,
default() {
let options: CountUpOptions = {
startVal: 0, // 开始的数字 一般设置0开始
decimalPlaces: 2, // number类型 小数位,整数自动添.00
duration: 2, // number类型 动画延迟秒数,默认值是2
useGrouping: true, // boolean类型 是否开启逗号,默认true(1,000)false(1000)
useEasing: true, // booleanl类型 动画缓动效果(ease),默认true
smartEasingThreshold: 500, // numberl类型 大于这个数值的值开启平滑缓动
smartEasingAmount: 300, // numberl类型
separator: ',',// string 类型 分割用的符号
decimal: '.', // string 类型 小数分割符合
prefix: '¥', // sttring 类型 数字开头添加固定字符
suffix: '元', // sttring类型 数字末尾添加固定字符
numerals: [] // Array类型 替换从0到9对应的字,也就是自定数字字符了,数组存储
}
return options
}
}
})
onMounted(() => {
initCount()
})
const initCount = () => {
numAnim = new CountUp(countupRef.value, props.end, props.options)
numAnim.start()
}
</script>
<template>
<span ref="countupRef"></span>
</template>
这时我们发现,在
onMounted
执行之后, 如果我们的endVal值发生了改动, 由于 CountUp.vue
的 onMounted
已经完成,并不会同步修改, 如果我们的值是异步获取的,会造成渲染不出我们想要的结果,那么我们就需要在组件中把这个 initCount
方法给暴露给父组件使用,在vue3中,我们只需要使用 defineExpose
暴露即可, 同时我们也进一步完善一下我们的props, 校验限制一下传入的optinos
值, 尽量避免使用上的错误, 同时修改一下默认值,避免造成一些问题,最终的代码如下<script setup lang="ts">
import { CountUp } from 'countup.js'
import type { CountUpOptions } from 'countup.js'
import { onMounted, ref } from 'vue'
let numAnim = ref(null) as any
const countupRef = ref()
const props = defineProps({
end: {
type: Number,
default: 0
},
options: {
type: Object,
validator(option: Object) {
let keys = ['startVal', 'decimalPlaces', 'duration', 'useGrouping', 'useEasing', 'smartEasingThreshold', 'smartEasingAmount', 'separator', 'decimal', 'prefix', 'suffix', 'numerals']
for (const key in option) {
if (!keys.includes(key)) {
console.error(" CountUp 传入的 options 值不符合 CountUpOptions")
return false
}
}
return true
},
default() {
let options: CountUpOptions = {
startVal: 0, // 开始的数字 一般设置0开始
decimalPlaces: 2, // number类型 小数位,整数自动添.00
duration: 2, // number类型 动画延迟秒数,默认值是2
useGrouping: true, // boolean类型 是否开启逗号,默认true(1,000)false(1000)
useEasing: true, // booleanl类型 动画缓动效果(ease),默认true
smartEasingThreshold: 500, // numberl类型 大于这个数值的值开启平滑缓动
smartEasingAmount: 300, // numberl类型
separator: ',',// string 类型 分割用的符号
decimal: '.', // string 类型 小数分割符合
prefix: '', // sttring 类型 数字开头添加固定字符
suffix: '', // sttring类型 数字末尾添加固定字符
numerals: [] // Array类型 替换从0到9对应的字,也就是自定数字字符了,数组存储
}
return options
}
}
})
onMounted(() => {
initCount()
})
const initCount = () => {
numAnim = new CountUp(countupRef.value, props.end, props.options)
numAnim.start()
}
defineExpose({
initCount
})
</script>
<template>
<span ref="countupRef"></span>
</template>
<style scoped lang='scss'></style>
版权声明:除特别声明外,本站所有文章皆是本站原创,转载请以超链接形式注明出处!