前几天我在做一件事,需要一个可见的计时器。 该项目中此类计时器有 UI 先例。 人们不想看到数字向下计时;理想情况下是看到一个“条”从满到空逐渐消失。 我之所以提到这一点,是因为您可以通过多种方式实现“计时器”UI。 这不是对所有这些方法的探讨(在 CodePen 上搜索 会更有帮助),而只是对对我来说有用的一种方法的探讨。
我需要的计时器类型是项目中称为“回合时间”的条形。 执行一个操作。 它可能会导致回合时间,并且大多数后续操作将在回合时间结束之前被阻止。 因此,一个非常清晰的红色条形向下计时是正确的 UI。 它提供了一种节奏和流动感,您可以从中感觉到计时器的结束时间并为下一步操作计时。

linear
动画,将条形缩小到零。设置起来相当容易……
为了以防万一我们想在某个时候对容器的空白部分进行样式设置,让我们给自己一个父/子元素。
<div class="round-time-bar">
<div></div>
</div>
现在,让我们只对内部的条形进行样式设置。
.round-time-bar div {
height: 5px;
background: linear-gradient(to bottom, red, #900);
}
这给了我们一个漂亮的小红色条形,我们可以用它来作为时间指示器。
接下来我们需要让它向下计时,但在这里我们需要考虑功能。 这样的计时器需要知道它正在计时多长时间! 我们可以直接在HTML中提供这些信息。 这并不意味着我们正在避免JavaScript - 我们正在拥抱它。 我们在说,“嘿,JavaScript,请给我们一个变量作为持续时间,我们会接着处理。”
<div class="round-time-bar" style="--duration: 5;">
<div></div>
</div>
事实上,这种方式对现代 DOM 处理 JavaScript 非常友好。 只要--variable
是正确的,它就可以随时重新渲染该 DOM 元素,我们可以确保设计可以很好地处理这一点。 我们将做一个会这样做的变体。
现在,让我们让动画发生。 好消息是,这很简单。 这是一个单行关键帧
@keyframes roundtime {
to {
/* More performant than animating `width` */
transform: scaleX(0);
}
}
我们可以“压缩”条形,因为条形的设计没有任何东西在水平缩放时会看起来被压缩。 如果我们有,我们可以对width
进行动画处理。 这不是那么大不了,尤其是因为它没有重新流式任何其他内容。
现在我们将它应用到条形上
.round-time-bar div {
/* ... */
animation: roundtime calc(var(--duration) * 1s) steps(var(--duration)) forwards;
transform-origin: left center;
}
看到我们是如何拉取--duration
变量来设置动画的持续时间的吗? 这完成了繁重的工作。 我也用它来设置相同数量的steps()
,以便它“向下计时”。 这种“计时”可能是您喜欢的视觉 UI 东西(我也喜欢),但它也适应了 JavaScript 可能会随时重新渲染此条形的概念,而计时使您不太可能注意到。 我使用了整数作为持续时间值,以便它可以像这样发挥双重作用。
但是,如果您想要平滑的动画,我们可以像这样进行变体处理,例如
<div class="round-time-bar" data-style="smooth" ... />
然后不要进行步骤处理
.round-time-bar[data-style="smooth"] div {
animation: roundtime calc(var(--duration) * 1s) linear forwards;
}
请注意,我们还使用了linear
动画,这似乎对计时器很有意义。 时间,正如它所是的那样,不会减速。 或者会吗? 无论如何,这是你的决定。 如果你想要一个看起来在某些点加速或减速的计时器,那就去做吧。
我们可以使用相同的变体数据属性驱动 API 来处理诸如颜色变体之类的事情
.round-time-bar[data-color="blue"] div {
background: linear-gradient(to bottom, #64b5f6, #1565c0);
}
最后一个变体是使每个“秒”具有固定的宽度。 这样,一个 10 秒的计时器看起来会比一个 5 秒的计时器长
.round-time-bar[data-style="fixed"] div {
width: calc(var(--duration) * 5%);
}
这是演示
注意其中用于重新启动 CSS 动画的小技巧。
哦,对了,我知道有一个<meter>
元素,它可能更具语义性,但它带来了自己的 UI,而我在这里并不希望它具有动画性——至少在没有与它作斗争的情况下。 但我想知道它是否更易于访问? 它是否以一种有用的方式宣布其当前值? 如果我们使用 JavaScript 实时更新<meter>
,它会是一个更易于访问的计时器吗? 如果有人知道,我可以在这里链接一个解决方案。
使用 style 不需要允许内联样式的 CSP(据我所知这是不鼓励的)吗?
我认为你可以这样做
并将
20secduration
添加到div.round-time-bar
的类列表中。您还可以使用
data-duration=20
并将var(--duration)
更改为attr(data-duration)
吗?<progress>
元素可能比<meter>
更具语义性,不确定……无论哪种都比<div>
更合适,这是肯定的。并且
<progress>
可以在 CSS 中进行样式设置。 不过,对值的动画处理可能需要在 JavaScript 中完成(通过操作其value
属性)。meter
被宣布为辅助技术的progressbar
。 会给出当前值,以及最小值和最大值。 这里的 UI 组件是通用的,需要一些 aria 属性来模仿行为。 我不太了解它如何被设备处理。 无论如何,我们需要更灵活的样式选项来处理本机 UI 元素!我很好奇想看看让条形递增但也能在秒之间平滑动画处理的难度有多大。 事实证明,这很简单。 而不是使用变量设置秒数,而是通过放置到容器中的子对象数量来设置秒数,每个子对象都有一个
n-1 秒
延迟的动画,并且容器被设置为使用 flexbox 反向显示它们。如果有人感兴趣,请点击链接
太棒了。
太棒了!
谢谢 Chris Coyier。
我已经寻找这个好几天了。
我很想将这些计时器添加到我创建的图像幻灯片中,让它与幻灯片同时运行,就像 Instagram 故事一样。 但我不知道如何让它工作。
希望能得到一些帮助。
我刚开始学习这个。
再次感谢。
是否有办法反转动画? 让计时器彩色条从左到右完成(而不是消失)?