数字滚动组件Get

在一个活动开发需求中需要用到一个带有数字滚动效果的倒计时组件,如图示:

效果:Slider UI - micro Interaction for Mobikul by Nitish Khagwal on Dribbble
项目技术栈:remix/tailwind

1、OK话不多说,我们先来写一位数的数字滚动组件: 

export const NumBlock = ({ num = 0 }: { num: number }) => {
  return (
    <ul
      style={{ transform: `translateY(-${num * 44}px)` }} //偏移高度为数字*该ul的高度
      className="oswald ease-in-expo h-11 w-7 flex-1 text-center transition-all duration-200 sm:w-9" //oswald字体、ease-in-expo动画效果 根据自身需求调整
    >
      {new Array(10).fill(0).map((t, i) => (
        <li
          key={i}
          className="list-none bg-[#0F051D] py-1.5 text-2xl text-white"
        >
          {i}
        </li>
      ))}
    </ul>
  );
};

2、因为小时、分钟、秒钟最多都是两位,所以我们来一个两位数组合件:

export const ModalBlock = ({ unit, num }: { unit: string; num: number }) => {
  if (num > 99) return;

  const i: number = ~~(num / 10); //十位数
  const j: number = num % 10; //个位数

  return (
    <div className="flex h-20 w-16 flex-col items-center justify-between space-y-1 p-1 pt-2 sm:w-20">
      <div className="flex items-center space-x-1">
        <div className="h-11 w-full overflow-hidden rounded">
          <NumBlock num={i} />
        </div>
        <div className="h-11 w-full overflow-hidden rounded">
          <NumBlock num={j} />
        </div>
      </div>
      <span className="text-muted-background">{unit}</span>
    </div>
  );
};

3、接下来我们可以根据我们的UI需求进行组合:

export const TimeBlock = ({
  time: { day, hours, minutes, seconds },
}: {
  time: {
    day: number;
    hours: number;
    minutes: number;
    seconds: number;
  };
}) => {
  return (
    <div className="flex w-full items-center space-x-2 sm:space-x-6">
      <ModalBlock unit="D" num={day} />
      <ModalBlock unit="H" num={hours} />
      <ModalBlock unit="M" num={minutes} />
      <ModalBlock unit="S" num={seconds} />
    </div>
  );
};

4、最后就是倒计时逻辑了,必不可少要传入的参数就是我们的过期/开始时间:

let timer: any;

const ScrollNumber = ({ targetTime }: { targetTime: string }) => {
  let time = ~~((Date.parse(targetTime) - Date.now()) / 1e3); //距当前时间的秒数
  time = Math.abs(time); //取整
  let day: number = ~~(time / 86400);
  let hours: number = ~~((time - day * 86400) / 3600);
  let minutes: number = ~~((time - day * 86400 - hours * 3600) / 60);
  let seconds: number = time % 60;
  const [timeObj, setTimeObj] = useState({ day, hours, minutes, seconds });
  
  clearInterval(timer);
  
  timer = setInterval(() => {
    if (time <= 0) { //小于当前时间,递增
      if (++seconds > 59) {
        seconds = 0;
        if (++minutes > 59) {
          minutes = 0;
          if (++hours > 23) {
            hours = 0;
            ++day;
          }
        }
      }
    } else { //大于当前时间,递减
      if (seconds-- < 1) {
        seconds = 59;
        if (--minutes < 1) {
          minutes = 59;
          if (--hours < 1) {
            hours = 23;
            --day;
          }
        }
      }
    }
    setTimeObj({ day, hours, minutes, seconds });
  }, 1e3);
  return <TimeBlock time={timeObj} />;
};

export default ScrollNumber;
🥳🥳🥳至此一个带有滚动效果的倒计时组件就完成啦~~其中代码逻辑还有许多不足,欢迎大家给我提出宝贵建议噢~~💕💕
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值