龙空技术网

时钟和倒计时:CSS 和 JavaScript 中的计时

启辰8 60

前言:

眼前咱们对“js毫秒转换成日期格式怎么设置”大体比较关怀,我们都想要学习一些“js毫秒转换成日期格式怎么设置”的相关资讯。那么小编同时在网上收集了一些有关“js毫秒转换成日期格式怎么设置””的相关知识,希望同学们能喜欢,同学们一起来了解一下吧!

有一天,我需要一个数字时钟组件,所以我很快编写了一个简单的 JavaScript 方法:

function uiDigitalClock(node) {  const now = () => {    node.textContent = new Date().toLocaleTimeString()    requestAnimationFrame(now)  }  now()}

我在某处读到,这requestAnimationFrame应该比 更好的性能setInterval,但该方法一直困扰着我。

在最佳条件下,每秒requestAnimationFrame触发60 次——这比数字时钟需要的多 60 倍!

Date()每秒创建 60 次对象对性能来说并不好!

所以我尝试了setInterval:

function interval(node){  return setInterval(() => node.textContent = new Date().toLocaleTimeString(), 1000)}

同样,代码不多,视觉结果是相同的 - 并且每秒只有一个对象。 Date()

又怎样呢setTimeout()?

function timeout(node) {  const now = () => {    node.textContent = new Date().toLocaleTimeString()    setTimeout(now, 1000)  }  now()}

它也能得到类似的结果,但有令人讨厌的延迟(setImmediate()仅在 Node 中)

然后我决定修改初始版本,只每秒触发一次,并requestAnimationFrame()返回时间戳:

function frame(node) {  let last = 0;  const render = now => {    if (!last || now - last >= 1000) {      last = now;      node.textContent = new Date().toLocaleTimeString();    }    requestAnimationFrame(render);  }  window.requestAnimationFrame(render);}

当所有 3 个方法都运行时,我碰巧检查了开发工具中的标记,并注意到我什至无法扩展节点,因为它们不断刷新,并且看起来像旧的<blink>-tag!

向巴德寻求帮助

仍然不知道该选择哪种方法,我决定询问 Google Bard,它回答说:

Clock1使用该setInterval()方法创建一个每 1000 毫秒(1 秒)触发一次的循环计时器。这是性能最低的方法,因为它为每次迭代创建一个新的计时器,这可能会增加大量的开销。Clock2使用该setTimeout()方法,创建一个在 1000 毫秒后触发的计时器。这比clock1 性能更高,因为它不会为每次迭代创建新的计时器。然而,它的性能仍然不如clock3,因为浏览器必须等待计时器触发才能更新文本内容。Clock3使用该requestAnimationFrame()方法,这是请求浏览器重绘的更有效方法。浏览器只会在必要时重新绘制元素,这可以节省大量的 CPU 时间。

好吧,我决定使用clock3 ...但后来我突然想到:“ CSS 中的数字动画怎么样?使用@property?

Jhey不久前制作了一个纯 CSS 秒表,所以我决定尝试类似的东西。

@property --seconds {  syntax: "<integer>";  initial-value: 0;  inherits: false;}@property --minutes {  syntax: "<integer>";  initial-value: 0;  inherits: false;}@property --hours {  syntax: "<integer>";  initial-value: 0;  inherits: false;}

然后,在<ol>-tag 中,我<li>为每个时间单位添加了一个 -tag。

要使用 - 声明的值@property,您需要使用 CSS 计数器,因此几秒钟内它是:

.seconds {  animation: seconds 60s steps(60, end) infinite;  animation-delay: var(--delay-seconds, 0s);  counter-reset: seconds var(--seconds);  &::after { content: counter(seconds, decimal-leading-zero) ' '; }}

要为秒设置动画,需要一个关键帧:

@keyframes seconds {   from { --seconds: 0;}  to { --seconds: 60; }}

对于几分钟来说,几乎是一样的,但是动画花费了 60 倍的时间 (60 x 60 = 3600):

animation: minutes 3600s steps(60, end) infinite;

对于几个小时,我们需要将该数字乘以 24:

animation: hours 86400s steps(24, end) infinite;

耶!我们有一个可以工作的 CSS 时钟……但它只在午夜工作,因为小时、分钟和秒都从0(零)开始。

那么该怎么办?创建初始对象后,我可以轻松地从 JavaScript 更新属性Date()。

但这样动画就会出错,因为它们会运行相同的时间(每秒钟 60 秒),即使实际的秒数小于该值。

我在 Twitter 上寻求帮助——幸运的是,Temani Afif 和 Álvaro Montoro 回复了!解决方案是使用负数 animation-delay。

因此,使用一些 JavaScript 来设置当前时间并计算延迟:

const time = new Date();const hours = time.getHours();const minutes = time.getMinutes();const seconds = time.getSeconds();// Delaysconst HOURS = -Math.abs((hours * 3600) + (minutes * 60) + seconds);const MINS = -Math.abs((minutes * 60) + seconds);const SECS = -Math.abs(seconds);

...我们可以更新之前指定的 CSS 属性,例如:

node.style.setProperty(`--delay-seconds`, `${seconds}s`);

现在,我们有了一个可以工作的数字 CSS 时钟——将其与此处的其他方法进行比较:

如果您在开发工具中检查标记,您会发现 CSS 版本并未重写 DOM 内容。

倒数

之后,我决定重新审视我的旧 Codepen,多语言倒计时,并制作一个纯 CSS 版本:

locale如果您想要其他语言,您可以在 JS 代码中使用:

但性能呢?CSS 可能不会像 JavaScript 那样阻塞主线程,但我们能确定它使用 GPU 而不是 CPU 吗?

有一个老技巧:

.useGpu {  transform: translateZ(0);  will-change: transform;}

然后,在开发工具中,转到“图层”:

看到“倒计时”现在如何拥有自己渲染层了吗?不确定这是否仍然适用,但我猜添加也没什么坏处。

离开浏览器选项卡

当我离开浏览器选项卡并返回时,纯 CSS 时钟没有出现任何问题。也许是我等的时间还不够长吧!但如果您遇到任何问题,请使用此事件重新计算时钟的延迟:

document.addEventListener('visibilitychange', () => {  if (!document.hidden) { ... }})
模拟时钟

作为奖励 - 这是一个模拟时钟,我不久前做了:

标签: #js毫秒转换成日期格式怎么设置 #js做秒表 #倒计时秒js #js当前时间时间戳 #js中计时器怎么写