继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

用CSS制作时钟和手表:从模拟时钟到Web组件

噜噜哒
关注TA
已关注
手记 247
粉丝 8
获赞 26

几年前,当 CSS 三角函数开始流行起来时,我写了一篇关于它们的文章。其中一个例子是我用纯 CSS 做的一个模拟时钟。使用新 CSS sin 和 cos 三角函数制作一个时钟

从那以后,CSS 引入了很多新特性——其中之一是 offset-path,它非常适合用来创建钟表上的指针(我听起来像是个钟表专家,但我其实是上网查的)。

所以,不啰嗦,直接来吧!让我们通过添加一些酷炫的功能来扩展我之前的例子。我们将把它包装成一个Web组件,以方便定制。但如果你想的话,你也可以只用CSS。

……

首先,我们设置一个简单的网格,将其分为3行:

主网格图如下所示(点击可查看大图)

    :host { /* 选择器,表示当前元素 */
      aspect-ratio: 1; /* 设置宽高比为1,即正方形 */
      background: #f2f2f2; /* 背景颜色为#f2f2f2 */
      border-radius: 50%; /* 圆角半径为50%,即圆形 */
      display: grid; /* 使用网格布局 */
      grid-template-rows: repeat(3, 1fr); /* 网格行定义为重复3次,每行占1份 */
    }

进入全屏 退出全屏

这些索引元素是一组 <li> 元素,使用 offset-distance / path 将它们围绕圆周分布。

    li {
      display: inline-block;
      list-style: none;
      offset-distance: var(--_d);
      offset-path: content-box;
      width: fit-content;
    }

切换到全屏 关闭全屏

每个 <li> 都有一个实际上的百分比,定义在 --_d 自定义属性中:

    <li style="--_d:0%">|</li>

进入全屏,退出全屏

这就给我们带来了:

索引值

默认情况下,offset-rotate 会自动旋转元素以跟随路径方向。这种行为正符合索引的需求,因此我们无需设置额外的旋转。

接下来,对于数字,我们将使用 <li> 标签,但这次是在一个有序列表 <ol> 中。

以下是第一项用旋转了300度的样式呈现的有序列表:

全屏播放 退出全屏

我们将使用cos()sin()函数来放置数字,就像我在前面举的例子那样。

    li {
      --_r: calc((100% - 15cqi) / 2);
      --_x: calc(var(--_r) + (var(--_r) * cos(var(--_d))));
      --_y: calc(var(--_r) + (var(--_r) * sin(var(--_d))));
      aspect-ratio: 1;
      display: grid;
      left: var(--_x);
      place-content: center;
      position: absolute;
      top: var(--_y);
      width: 15cqi;
    }

全屏(点击进入/退出)

于是我们得到了:

数字图片

现在,让我们为手和日期创建标记。我花了很多时间才想清楚这里应该用什么样的语义化的标记比较好?最后我放弃了,就用了好多 <div> 标签 😄
帽子将用伪元素来实现。

    <nav part="hands">
      <div part="seconds"></div>
      <div part="minutes"></div>
      <div part="hours"></div>
      <time part="时间"></time>
    </nav>

切换到全屏模式,结束全屏模式

我们将 <nav> 放置在主网格的中间行,然后创建一个三列的网格:

:host::part(hands) {
  display: grid;
  grid-area: 2 / 1 / 3 / 1;
  grid-template-columns: repeat(3, 1fr);
}

点击进入全屏模式,点击退出全屏

这就有了:
手(如图所示)

最后,我们将标签放在主网格最顶端最后一行的顶部中央位置:

标签(这张图片的标签)(点击这里查看图片)

……

制作双手动画

让双手动起来,我们只需要一个简单的手部动画,

    @keyframes turn {
      to { transform: rotate(1turn); }
    }

注:代码片段保持不变。

全屏模式,退出全屏

然而,它需要以三种截然不同的方式使用。

    :host::part(hours) {
      animation: turn 43200s linear infinite;
      animation-delay: var(--_dh, 0ms);
    }
    :host::part(minutes) {
      animation: turn 3600s steps(60, end) infinite;
      animation-delay: var(--_dm, 0ms);
    }
    :host::part(seconds) {
      animation: turn 60s linear infinite;
      animation-delay: var(--_ds, 0ms);
    }

全屏 全屏退出

就这样啦!……如果这没问题的话,如果你不介意时钟总是从中午十二点重新开始的话!

为了用实际时间来初始化这个时钟,我们需要更新延迟属性:--_dh--_dm--_ds — 为此,我们需要一小段JavaScript代码:

    const time = new 日期();
    const hour = -3600 * (time.getHours() % 12);
    const mins = -60 * time.getMinutes();
    app.style.setProperty('--_dm', `${mins}s`);
    app.style.setProperty('--_dh', `${(hour + mins)}s`);

进入全屏,退出全屏

变种

样式变体超级简单(请参见文章最后的演示)。

来一杯 SAIKO,(一种流行饮料)

SAIKO

或者一个 ROBEX(抱歉,我的命名缺乏创意)

ROBEX
ROBEX机器人

或者來點非常色彩鮮豔的例子吧

缅甸、泰国和印度

当然,这可以通过手动添加标签来实现,但是,如果我们将其包装在一个 web 组件中,维护起来会更加方便。

    <analog-clock
      label="မြန်မာ"
      system="mymr"
      timezone="+6.5"
      class="burmese"
      indices
      marker="•">
    </analog-clock>

    <analog-clock
      label="ประเทศไทย"
      system="thai"
      timezone="+7"
      class="thai"
      indices
      marker="·"
      marker-hour="•">
    </analog-clock>

    <analog-clock
      label="अरुणाचल"
      system="wcho"
      timezone="+5.5"
      class="indian">
    </analog-clock>

全屏 退出全屏

咱们看看吧。

以下

网页组件

你可以用 <analog-clock> web 组件轻松地在你的网页项目中添加一个模拟时钟。它有很多自定义选项,比如属性和 CSS 自定义属性。

安装和使用

使用npm: 安装

``
npm i @browser.style/analog-clock
```安装一个模拟时钟的npm包

切换到全屏模式 退出全屏

或者直接通过 CDN 访问

    <script src="https://browser.style/ui/analog-clock/index.js" type="module"></script> <!-- 引入模拟时钟的JS文件 -->

切换到全屏模式,退出全屏

接着,只需将这个组件添加到你的HTML里。

    <analog-clock></analog-clock>

进入全屏 退出全屏

一些基本的例子

以下是一些常见的应用场景

    <!-- 简单的纽约时间时钟 -->
    <analog-clock 
      label="纽约" 
      timezone="-4">
    </analog-clock>

    <!-- 带日期显示和分钟标记的时钟 -->
    <analog-clock 
      indices=" "
      date="天 月" 
      label="当前时间">
    </analog-clock>

    <!-- 采用罗马数字和自定义标记的时钟 -->
    <analog-clock 
      indices="小时"
      system="罗马"
      marker="•"
      marker-hour="●"
      label="罗马">
    </analog-clock>

全屏模式,退出全屏

样式例子

这个组件可以通过CSS自定义属性(即CSS变量)来设置样式。

    /* 黄金奢华主题 */
    .luxury {
      --analog-clock-bg: radial-gradient(
        circle at 50% 50%,
        #f4e5c3 50%,
        #e2ca7d 51%,
        #5c4d28 95%
      );
      --analog-clock-c: #2a2317;
      --analog-clock-ff: "Didot",衬线体;
      --analog-clock-second: #8b0000;
      --analog-clock-cap: #403428;
    }

    /* 极简风格 */
    .minimal {
      --analog-clock-bg: #fff;
      --analog-clock-c: #333;
      --analog-clock-indices-c: #ddd;
      --analog-clock-second: #ff4444;
      --analog-clock-cap-sz: 4cqi 像素;
    }

进入全屏模式 退出全屏模式

计数系统

属性 system 支持各种数制,如我们之前看到的:

    <模拟时钟 系统="mymr"></模拟时钟>
    <模拟时钟 系统="thai"></模拟时钟>

全屏 退出全屏

时区设置

你可以通过设置 timezone 属性来显示不同的时区:

    <analog-clock label="纽约市" timezone="-4:00"></analog-clock>
    <analog-clock label="伦敦市" timezone="0"></analog-clock>
    <analog-clock label="东京市" timezone="+9"></analog-clock>
    <analog-clock label="孟买" timezone="+5.5"></analog-clock>

按全屏模式;按退出全屏

属性
  • date: 显示日期。取值可为 "day"、"month"、"year" 或它们的任意组合。
  • indices: 显示刻度标记。值:空(60个标记)或 "hours"(12个标记)
  • label: 显示在时钟下方的文本标签
  • marker: 用于刻度的字符(默认值为 "|")。
  • marker-hour: 用于小时刻度的字符(默认值与 marker 相同)
  • numerals: 显示的数字个数(1-12,默认值:12)
  • steps: 使用逐帧动画显示秒针的走动
  • system: 数字系统。取值可为 "roman"、"romanlow" 或任何有效的 Intl numberingSystem
  • timezone: UTC 偏移量,以小时为单位(如 "-4"、"+1"、"+5.5")
演示

这里有一个Codepen,包含了我们制作的时钟和手表。

现在去教孩子们读模拟表吧!

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP