前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >发明专利公开 -- CSS动画精准实现时钟

发明专利公开 -- CSS动画精准实现时钟

作者头像
奋飛
发布2023-05-13 14:48:36
9250
发布2023-05-13 14:48:36
举报
文章被收录于专栏:Super 前端Super 前端

上一篇【setTimeout不准时,CSS精准实现计时器功能】的博文,最后提到了通过 CSS 动画实现计时器的方式。

本文详情描述如何通过 CSS 完整实现时钟效果,这也是团队 21 年专利的一项内容(专利公布号:CN114003087A)。

该发明专利主要解决大屏下通过 javascript 实现的时钟不准确的问题。通过 CSS 动画进行计时,避免同步阻塞卡顿的问题。

在这里插入图片描述
在这里插入图片描述

前置知识

伪元素

伪元素允许你对被选择元素的特定部分修改样式。

::after 用来创建一个伪元素,作为已选中元素的最后一个子元素。通常会配合content属性来为该元素添加装饰内容。这个虚拟元素默认是行内元素。

伪元素:before:after添加的内容默认是inline元素

  • 伪元素不属于文档,所以js无法操作它
  • 伪元素属于主元素的一部分,因此点击伪元素触发的是主元素的click事件
  • 块级元素才能有:before, :after,其实是不妥的,大部分行级元素也可以设置伪元素,但是像img可替换元素,因为其外观和尺寸有外部资源决定,那么如果外部资源正确加载,就会替换掉其内部内容,这时伪元素也会被替换掉,但是当外部资源加载失败时,设置的伪元素是可以起作用的。
示例
代码语言:javascript
复制
a::after {
	content: "→";
}

数据属性 data-*

HTML5 有扩展性的设计,它初衷是数据应与特定的元素相关联,但不需要任何定义。data-* 允许我们在标准内于 HTML 元素中存储额外的信息,而不需要使用类似于 classList 。

attr()

CSS 表达式 attr() 用来获取选择到的元素的某一 HTML 属性值,并用于其样式。它也可以用于伪元素,属性值采用伪元素所依附的元素。

attr() 理论上能用于所有的 CSS 属性但目前支持的仅有伪元素的 content 属性,其他的属性和高级特性目前是实验性的

示例

同 数据属性 结合,可以很好的实现相应的效果展示。

hover到 标签,展示对应 data-hover内容

css animation

animation 属性是 animation-name,animation-duration, animation-timing-function,animation-delay,animation-iteration-count,animation-direction,animation-fill-mode 和 animation-play-state 属性的一个简写属性形式。

属性

说明

示例

animation-name

指定应用的一系列动画

animation1,animation2

animation-duration

指定一个动画周期的时长,单位 s 或者 ms

60s

animation-timing-function

在每一动画周期中执行的节奏

ease、linear、steps(60)

animation-delay

定义动画于何时开始,单位 s 或者 ms

100ms

animation-iteration-count

定义动画在结束前运行的次数

infinite(无限次)、3

animation-direction

指示动画是否反向播放

normal、alternate、reverse

animation-fill-mode

设置 CSS 动画在执行之前和之后如何将样式应用于其目标

forwards、backwards

animation-play-state

定义一个动画是否运行或者暂停

running、paused

steps(number_of_steps, direction):定义了一个阶梯函数,将输出值的域等距地划分。

示例

动画周期的时长 10s ,等距划分为10步,每秒执行一次 timer,无限次循环执行。

代码语言:javascript
复制
animation: timer 10s infinite steps(10) forwards;

translate

transform: translate(x, y) / translate: x y; 平移变换。

示例
代码语言:javascript
复制
a:hover {
  translate: 200px 50px;
  /*等价于*/
  transform: translate(200px, 50px);
}

实现思路

在这里插入图片描述
在这里插入图片描述

步骤一:定义DOM

将时、分、秒进行DOM定义,针对时、分、秒将相关数据通过数据属性 data-* 进行绑定

代码语言:javascript
复制
<div class="card">
  <div class="card-hours"> 
    <div class="hours" data-hours="18 19 20 21 22 23 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17">div>
  div>
div>
<div class="card">:div>

<div class="card">
  <div class="card-minutes">  
    <div class="minutes"
         data-minutes="58 59 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57">
    div>
  div>
div>
<div class="card">:div>

<div class="card">
  <div class="seconds"
       data-seconds="50 51 52 53 54 55 56 57 58 59 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49">
  div>
div>

关于data-hoursdata-minutesdata-seconds 数据通过当前时间进行初始化(动态形式)。上述示例,初始时间为:18:58:50

上述,针对分钟、小时,多一层 DOM,

后续解释作用(见步骤四)。

步骤二:展示区域基础定义

这里针对:时、分、秒 统一设置。

在这里插入图片描述
在这里插入图片描述

设置一个固定大小的 font-size ,确保每行只能展示一个数字;同时,指定 line-height,确保可视区内只有展示一个数字。(为后续动画做准备)

代码语言:javascript
复制
body {
  font-size: 48px;
}
.card {
  display: inline-block;
  height: 68px;
  overflow: hidden;
}
.hours, .minutes, .seconds {
  width: 68px;
  line-height: 68px;
}
  • font-sizeline-height 属性,具有继承性,贯穿整个网页
  • font-sizeline-height 属性,和字体宽度没有必然的换算关系;如果希望字体是等宽的,需要使用等宽字体(如:Consolas、Monaco、monospace)

步骤三:实现「秒」

每一个周期60s,等距划分为60份(六十进制),每份1s,然后通过 translate 来展示下一个数值。

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
.seconds:after {
  display: block;
  content: attr(data-seconds);
  animation: counter 60s steps(60) infinite forwards;
}
@keyframes counter {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 -100%;
  }
}

步骤四:实现「分、时」

对于分钟、小时,滚动展示的逻辑同秒一致,只是切割的份数及单位时间需要根据实际的来。

  • 分钟:等距 60 份(六十进制),一个周期
60 * 60 = 3600
  • 小时:等距 24 份(二十四进制),一个周期 24 * 60 * 60 = 86400
代码语言:javascript
复制
.minutes:after {
  display: block;
  content: attr(data-minutes);
  animation: counter 3600s steps(60) infinite forwards;
  animation-delay: 10s;	/* 延后执行 */
}

.hours:after {
  display: block;
  content: attr(data-hours);
  animation: counter 86400s infinite steps(24) forwards;
  animation-delay: 70s; /* 延后执行 */
}

分钟、小时与秒不同的是,第一次进制大概率不是整 60 或 24。

以上述实例解释:当前秒为 50,再过 10s(计算方式:$ 60 - 50

),分钟就应该变成 59;同样的,再过 70s(计算方式:

3600 - 58*60 - 50 $),小时就应该变成 19。

所以,上述 animation-delay 就是让固定周期的动画,稍后开始,等待的时间就是依据初始时间计算而来。

animation-delay 指定从应用动画到元素开始执行动画之前等待的时间量

解释清楚了延迟的作用,但问题是:首次的动画如何执行?(上述 animation 是从等待后的完整周期开始的)

步骤一,中提到的

就是为此。

代码语言:javascript
复制
.card-minutes {
  height: 136px;
  overflow: hidden;
   /* 60-pastSeconds */
  animation: delay-counter 10s steps(1) 1 forwards;
}

.card-hours {
  height: 136px;
  overflow: hidden;
  /* 3600-pastMinutes*60-pastSeconds */
  animation: delay-counter 70s steps(1) 1 forwards;
}
@keyframes delay-counter {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 -50%;
  }
}

上述动画只执行一次(初始化)

总结

CSS 动画运行效果良好,甚至在低性能的系统上。渲染引擎会使用跳帧或者其他技术以保证动画表现尽可能的流畅。

同时动画在各个执行阶段,也提供了相应的事件,这里暂不展开,有诉求的可以查看相关 MDN AnimationEvent

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-05-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前置知识
    • 伪元素
      • 示例
    • 数据属性 data-*
      • attr()
        • 示例
      • css animation
        • 示例
      • translate
        • 示例
    • 实现思路
      • 步骤一:定义DOM
        • 步骤二:展示区域基础定义
          • 步骤三:实现「秒」
            • 步骤四:实现「分、时」
            • 总结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档