关于前端:你可能不需要JSCSS实现一个计时器

5次阅读

共计 3103 个字符,预计需要花费 8 分钟才能阅读完成。

CSS 当初可不仅仅只是改一个色彩这么简略,还能够做很多交互,比方做一个功能齐全的计时器?

款式上并不简单,次要是几个交互的中央

  1. 数字时钟的变动
  2. 开始、暂停操作
  3. 重置操作

如何仅应用 CSS 来实现这样的性能呢?一起看看吧

一、数字时钟的变动

这个性能之前在这篇文章中有具体介绍,有趣味的能够回顾一下

还在应用定时器吗?CSS 也能实现电子时钟

这里简略介绍一下实现原理

在以前,如果要实现数字的递增变动,可能须要提前准备好这些数字,例如像这样

<span>
    <i>1</i>
  <i>2</i>
  ...
  <i>59</i>
</span>

或者用伪元素创立也行

span::before{content: '1\A 2\A 3\A ... 59'}

这种形式须要创立多个标签,稍微繁琐,也不易扩大。当初有更简洁的形式能够实现了,那就是 CSS @property。这是干什么的呢?简略来讲,能够自定义属性,在这个例子中,能够让数字像色彩一样进行过渡和动画,可能不太懂,间接看例子吧

假如 HTML 是这样的

<span style="--num: 0"></span>

咱们让这个自定义变量在页面中展现进去,单纯的 content无奈间接显示自定义变量,须要借助计数器,有趣味的能够参考这篇文章:小 tips: 如何借助 content 属性显示 CSS var 变量值

span::after{counter-reset: num var(--num);
  content: counter(num);
}

当初能够通过 :hover 扭转这个数字

span:hover::after{--num: 59}

很僵硬的从 0 变成 59 了,十分合乎惯例,因为 --num 并不反对过渡动画。如果利用 CSS property,状况就不一样了,须要革新的中央很少,先定义一下--num,而后给这个变量一个过渡工夫,如下

@property --num { 
  syntax: '<integer>';
  inherits: false;
  initial-value: 0;
}
span::after{transition: 1s --num;}

神奇的一幕产生了

看着如同不堪设想?能够这么了解,通过 @property 定义后,这个变量自身能够独自设置过渡了,而不再取决于一些仅反对过渡的属性(colorwidth等)。还能够应用动画,如下

@keyframes num {
  to {--num: 10}
}
span{animation: num 1s infinite steps(10);
}

数字变动的基本原理就是这样了,一个有限循环的 CSS 动画!

回到这里,这里须要的是一个秒表,分为“分”、“秒”、“毫秒”(这里的毫秒就用 1/100 秒来代替),3 个数字的动画时长都不统一,所以须要定义 3 个 CSS 变量,残缺实现如下

@keyframes minitus {
  to {--m: 59}
}
@keyframes seconds {
  to {--s: 59}
}
@keyframes ms {
  to {--ms: 99}
}
span{counter-reset: minitus var(--m) seconds var(--s) ms var(--ms);
  animation: minitus 3600s infinite steps(60, end), 
    seconds 60s infinite steps(60, end), 
    ms 1s infinite steps(100, end);
}
span::before{content: counter(minitus, decimal-leading-zero) ':' counter(seconds, decimal-leading-zero) ':' counter(ms, decimal-leading-zero);
}

这样就失去了一个主动运行的秒表

二、开始、暂停操作

首先思考一下,CSS 须要怎么记住点击操作?答案就是 input type="checkbox"(通过label 关联),能够这样来布局

<div class="counter">
  <input type="checkbox" id="start" hidden>
  <label class="btn start" for="start"></label>
  <label class="btn reset"> 重置 </label>
  <div class="clock"></div>
</div>

因为须要通过 input:cheked 来管制秒表的状态,须要借助后置兄弟选择器 ~ 来实现,所以 input 须要在后面(当然,当初有了 :has 也能够不须要这样)。

这里能够通过 grid 布局来灵便摆放各个模块的地位

.counter{
  display: grid;
  grid-template-areas:
    "clock clock"
    "start reset"
}
.start{
  /**/
  grid-area: start;
}
.reset{
  /**/
  grid-area: reset;
}

简略丑化当前,能够失去这样的成果

而后,因为秒表的运行其实就是一个 CSS 动画,所以咱们能够间接用 :cheked 来管制动画的状态,默认设置成暂停的,还有按钮文字也能够通过 ::before 来生成,实现如下

.clock{animation-play-state: paused;/* 默认暂停 */}
.start::before{content: '开始';}
:checked~.start::before{content: '暂停';}
:checked~.clock{animation-play-state: running;}

这样就能够通过按钮手动管制开始和暂停了

三、重置操作

重置看起来如同有点麻烦,有点无从下手。

其实重置一个动画非常简单,间接将动画勾销就能够了,也就是相当于重置了动画,如下

.reset:active+.clock{animation: none;}

其次,重置个别只有在暂停时才可用,所以还须要用后面的 :checked 禁用一下,并且视觉上能够透明度升高一点,实现如下

:checked~.reset{
  opacity: .65;
  pointer-events: none;
}

这样就失去了文章结尾所示的成果

当然,你还能够应用自定义字体,比方DigitalNumbers

残缺代码能够查看以下任意链接:

  • CSS counter (codepen.io)
  • CSS counter (runjs.work)

四、会影响业务逻辑吗?

还有一点,有同学放心 CSS 只是视觉层面的,可能会影响业务逻辑。

的确,因为是伪元素渲染,页面上看不到任何数字,也就是无奈间接通过 innerText 获取以后工夫,然而,咱们能够借助 getComputedStyle 来失去 CSS 变量

getComputedStyle($0).getPropertyValue('--ms')

实时获取如下

所以通过 CSS 形式也是齐全不影响业务逻辑的

五、兼容性和总结

因为在实现中用到了 CSS @property 个性,这是 CSS Houdini 的一部分,目前只有 Chrome 反对(惋惜了😥)。让人惊奇的是,Safari竟然在前不久也反对了这个个性,将来可期,如下

当然这不是重点,只是这种形式实现更加简洁而已,齐全能够用传统形式来实现,有趣味的能够尝试一下。

上面总结一下实现要点

  1. CSS 当初很弱小,不仅仅只是款式,还能做很多交互
  2. CSS @property 能够使 CSS 变量反对动画
  3. 数字时钟的变动其实是一个 CSS 变量一直递增循环的动画
  4. CSS 点击操作状态能够通过 :checked 管制
  5. Grid 布局能够很不便的管制各个元素的地位
  6. 计时器开始和暂停其实就是动画的运行和暂停
  7. 间接将动画勾销就相当于重置了整个动画

最初,如果感觉还不错,对你有帮忙的话,欢送点赞、珍藏、转发❤❤❤

正文完
 0