react hooks 封一个简易版本的数字滚动动画

293 阅读1分钟

import { useEffect, useState } from 'react';
import { timer } from 'rxjs';
import { takeWhile } from 'rxjs/operators';
import { Props } from './typesing';

/** 数字递减动画组件
 * @param startTime 开始时间
 * @param endTime 结束时间
 * @param open 是否开启动画
 * @returns
 */
/** */
const Counter = ({
  startTime,
  endTime,
  time = 1000, // 默认1秒之内整个动画完成
  open = true,
}: Props) => {
  const [count, setCount] = useState(startTime);
  useEffect(() => {
    if (!open) {
      return;
    }
    const step = endTime <= time ? 1 : Math.ceil(endTime / time);

    const sub = timer(0, 1) // 设置一个定时器,每一毫秒执行一次
      .pipe(
        takeWhile((val) => {
          setCount((pre) => (pre - step < endTime ? endTime : pre - step));

          return val < Math.min(startTime - endTime, time);
        }),
      )
      .subscribe();
    return () => sub.unsubscribe();
  }, [endTime, time, startTime, open]);

  return <>{open ? count : startTime}</>;
};

export default Counter;