还在使用定时器吗?有点离谱的 CSS 电子时钟
The following article is from 前端侦探 Author XboxYan
通常要做一个时钟,肯定离不开 JS 定时器。今天换一种思路,用 CSS 来实现一个时钟,如下:
一、数字的变换
<span>
<i>1</i>
<i>2</i>
...
<i>59</i>
</span>
<span style="--num: 0"></span>
content
无法直接显示自定义变量,需要借助定时器,有兴趣的可以参考这篇文章:小tips: 如何借助content属性显示CSS var变量值[4]span::after{
counter-reset: num var(--num);
content: counter(num);
}
:hover
改变这个数字span:hover::after{
--num: 59
}
--h
,然后给这个变量一个过渡时间,如下@property --h {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
span::after{
transition: 1s --num;
}
神奇的一幕发生了
看着好像不可思议?可以这么理解,通过@property
定义后,这个变量本身可以单独设置过渡了,而不再取决于一些仅支持过渡的属性(color
、width
等)。甚至还能加上动画,需要用到steps
方法,设置动画周期为无限,如下
@keyframes num {
to {
--num: 10
}
}
span{
animation: num 1s infinite steps(10);
}
时钟的基本运行原理就是这样了,一个无限循环的 CSS 动画!
二、时、分、秒
下面来看具体时、分、秒的实现,HTML 如下
<div class="time">
<span class="hour"></span>
<a class="split">:</a>
<span class="minitus"></span>
<a class="split">:</a>
<span class="seconds"></span>
</div>
@property --h {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@property --m {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@property --s {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
.hour::after{
counter-reset: hour var(--h);
content: counter(hour);
}
.minitus::after{
counter-reset: minitus var(--m);
content: counter(minitus);
}
.seconds::after{
counter-reset: seconds var(--s);
content: counter(seconds);
}
没错,就是你想的,时针是0-23
,时长24h
,分针是0-59
,时长60min
,秒针是0-59
,时长60s
,但是 CSS 中的时间单位只支持秒(s)
或者毫秒(ms)
,所以这里需要转换一下,时长分别是60s*60*24
、60s*60
、60s
,具体实现如下:
@keyframes hour {
to {
--h: 24
}
}
@keyframes minitus {
to {
--m: 60
}
}
@keyframes seconds {
to {
--s: 60
}
}
.hour::after{
counter-reset: hour var(--h);
content: counter(hour);
animation: hour calc(60s * 60 * 24) infinite steps(24);
}
.minitus::after{
counter-reset: minitus var(--m);
content: counter(minitus);
animation: minitus calc(60s * 60) infinite steps(60);
}
.seconds::after{
counter-reset: seconds var(--s);
content: counter(seconds);
animation: seconds 60s infinite steps(60);
}
三、时、分、秒自动补零
decimal-leading-zero
来实现,具体做法如下.hour::after{
/**/
content: counter(hour, decimal-leading-zero);/*添加计数器样式*/
}
四、时间初始化
00:00:00
开始了,所以需要手动指定一下初始时间。假设现在是19:26:30
,如何初始化呢?animation-delay
来提前运动到未来指定位置,为了方便控制,使用三个变量--dh
、--dm
、--ds
来表示初始时间,注意,由于animation-delay
也只支持秒(s)
或者毫秒(ms)
,所以也同样需要转换,实现如下:root{
--dh: 19;
--dm: 26;
--ds: 30;
}
.hour::after{
/**/
animation: hour calc(60s * 60 * 24) infinite steps(24);
animation-delay: calc( -60s * 60 * var(--dh) );
}
.minitus::after{
/**/
animation: minitus calc(60s * 60) infinite steps(60);
animation-delay: calc( -60s * var(--dm) );
}
.seconds::after{
/**/
animation: seconds 60s infinite steps(60);
animation-delay: calc( -1s * var(--ds) );
}
const d = new Date()
const h = d.getHours();
const m = d.getMinutes();
const s = d.getSeconds();
document.body.style.setProperty('--ds', s)
document.body.style.setProperty('--dm', m + s/60)
document.body.style.setProperty('--dh', h + m/60 + s/3600)
五、闪烁的分隔符
@keyframes shark {
0%, 100%{
opacity: 1;
}
50%{
opacity: 0;
}
}
.split{
animation: shark 1s step-end infinite;
}
六、总结一下
CSS 实现本质是无限循环的 CSS 动画 灵活运用 CSS calc 计算 CSS 计数器可以将 CSS 变量通过 content 显示在页面 数字的变化现在可以通过 CSS @property 配合动画实现 时分秒的区别在于各自的动画时长、动画起始点不同 CSS 自动补零可以参考之前的文章,这里采用 decimal-leading-zero 实现 时间初始化其实就是指定动画 delay 值 指定初始值时还需要考虑到各自的偏移量,例如 19:30:30,此时的时针数字其实是 30.5 分隔符的闪烁动画
参考资料
CSS time (codepen.io): https://codepen.io/xboxyan/pen/OJOdvyy
[2]CSS @property: https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property
[3]CSS @property,让不可能变可能: https://juejin.cn/post/6951201528543707150
[4]小tips: 如何借助content属性显示CSS var变量值: https://www.zhangxinxu.com/wordpress/2019/05/content-css-var/
[5]CSS time (codepen.io): https://codepen.io/xboxyan/pen/OJOdvyy
- EOF -
觉得本文对你有帮助?请分享给更多人
关注「大前端技术之路」加星标,提升前端技能
点赞和在看就是最大的支持❤️