读数,可设置时间,间隔位数,分隔符

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)}</>
  )
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值