import React, { memo, useCallback, useEffect, useState, useRef, useMemo } from 'react';
const minTime = 20; // 定时器最小执行时间
// 使用方法
{/* <CountUp
end={423423}
separator=','
splitNum={3}
/> */}
// start:执行开始数字
// end: 执行结束数字
// separator: 分隔符
// splitNum: 隔几位分割
// duration: 执行动画时间,默认1S - 2S
// maxDefaultDuration: 默认最大执行时间
export default memo(({
start = 0,
end = 0,
separator = ',',
splitNum = 4,
duration = 0,
maxDefaultDuration = 2000
}) => {
const [value, setValue] = useState(start);
// 定时器执行时间
const time = useMemo(() => {
let newtime = minTime;
const durationNum = end - start;
// 定义了时间,而且时间间隔小于 定时器最小执行时间,按照标准执行
if(duration >= 0 && (duration / durationNum) > minTime ) {
newtime = duration / durationNum
}
// 没定义时间,时间小于1S时按照1s执行
if(duration === 0 && durationNum < (1000 / minTime) ) {
newtime = 1000 / durationNum
}
return newtime
}, [start, end, duration])
// 每秒读数间隔
const stepNum = useMemo(() => {
let newStepNum = 1;
const durationNum = end - start;
if(duration === 0 && durationNum > (maxDefaultDuration / minTime)) { // 读数超过设置最大值跳着读
newStepNum = parseInt(durationNum / (maxDefaultDuration / minTime)) + 1
} else if(duration > 0 && durationNum > (duration / minTime)) { // 规定时间读不完数跳着读
newStepNum = parseInt(durationNum / (duration / minTime)) + 1
}
if(newStepNum % 10 === 0 && newStepNum % 2 === 0) { // 为了好看防止不读个位数
newStepNum ++;
}
return newStepNum
}, [start, end, duration, maxDefaultDuration])
const timerRef = useRef(null)
const changeValue = useCallback(() => {
timerRef.current = setInterval(() => {
setValue(prev => {
const newValue = prev + stepNum < end ? prev + stepNum : end;
return newValue
})
}, time)
}, [time, stepNum, end])
// 数据按照间隔处理
const formatValue = useCallback(value => {
const newArr = [];
const valueArr = String(value).split('');
valueArr.reverse();
valueArr.forEach((item, index) => {
newArr.push(item);
if(splitNum > 0 && index % splitNum === splitNum-1 && index < valueArr.length-1) {
newArr.push(separator)
}
})
return newArr.reverse().join('')
}, [splitNum, separator])
useEffect(() => {
value >= end && clearInterval(timerRef.current)
}, [value, end])
useEffect(() => {
changeValue();
return () => {
clearInterval(timerRef.current)
}
}, [changeValue])
return (
<>{formatValue(value)}</>
)
})
10-16
3369
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
09-23
1540
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交