几年前,当 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,(一种流行饮料)
或者一个 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 class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="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 numberingSystemtimezone
: UTC 偏移量,以小时为单位(如 "-4"、"+1"、"+5.5")
这里有一个Codepen,包含了我们制作的时钟和手表。
现在去教孩子们读模拟表吧!
共同学习,写下你的评论
评论加载中...
作者其他优质文章