百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

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

toyiye 2024-08-22 22:55 5 浏览 0 评论


有一天,我需要一个数字时钟组件,所以我很快编写了一个简单的 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();

// Delays
const 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) { ... }
})

模拟时钟

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


相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码