在一个活动开发需求中需要用到一个带有数字滚动效果的倒计时组件,如图示:
![](https://img-blog.csdnimg.cn/direct/77b5f0f0a2b247d8bab5a931036a70c3.png)
项目技术栈: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;
🥳🥳🥳至此一个带有滚动效果的倒计时组件就完成啦~~其中代码逻辑还有许多不足,欢迎大家给我提出宝贵建议噢~~💕💕