渐变已经成为 CSS 领域的一部分相当长的时间了。 我们在许多项目中看到了很多径向渐变和线性渐变,但有一种渐变似乎有点孤独:圆锥渐变。 我们将使用这种类型的渐变制作一个表盘。
使用圆锥渐变
我们制作的是一个渐变,其颜色过渡围绕中心点旋转,并且可以具有多个颜色值。 为了使这个时钟正常工作,我们还将使用圆锥渐变的角度值,该值定义了旋转或起点。 角度是使用 from
值定义的。
background-image: conic-gradient(from 45deg, #6e7dab, #5762d5);
有趣的是,在 CSS 中,起始角度可以是负值,这将在后面派上用场。
一个简单的圆锥渐变示例
构建基本时钟
让我们从为时钟和指针添加一些 HTML 代码开始。
让我们为我们的时钟创建一些默认样式。 为了使它正常工作,我们稍后将使用 JavaScript 更新 CSS 变量,因此让我们将这些变量的作用域限定在 .clock
选择器中。 为了便于调整,让我们也添加指针的颜色。
.clock {
/* general clock vars */
--hour-hand-color: #000;
--hour-hand-degrees: 0deg;
--minute-hand-color: #000;
--minute-hand-degrees: 0deg;
--second-hand-color: hotpink;
--second-hand-degrees: 0deg;
position: relative;
min-width: 320px;
width: 25vw;
height: 25vw;
min-height: 320px;
border-radius: 50%;
margin: 0 auto;
border: 7px solid #000;
}
/* clock hands */
.hand {
position: absolute;
left: 50%;
bottom: 50%;
height: 45%;
width: 4px;
margin-left: -2px;
background: var(--second-hand-color);
border-radius: 6px;
transform-origin: bottom center;
transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
}
.second-hand {
transform: rotate(var(--second-hand-degrees));
}
.hour-hand {
height: 35%;
border-radius: 40px;
background-color: var(--hour-hand-color);
transform: rotate(var(--hour-hand-degrees));
}
.minute-hand {
height: 50%;
background: var(--minute-hand-color);
transform: rotate(var(--minute-hand-degrees));
}
这为我们提供了时钟所需的一般样式。 我们已在指针上设置了 transform-origin
,以便它们围绕时钟表盘正确旋转。 那里还有几个自定义属性,用于在指针上设置角度,我们将在使用 JavaScript 更新它们,以确保每个指针分别对应秒、分和时,从而获得正确的计时。
到目前为止,我们已经做到了以下几点。
好的,让我们继续更新这些自定义属性!
添加基本时钟的 JavaScript 代码
首先,我们将定位我们的时钟并创建一个函数。
const clock = document.getElementById("clock");
function setDate() {
// Code to set the current time and hand angles.
}
setDate();
在我们的函数中,我们将使用 Date()
函数 获取当前时间,以计算指针的正确角度。
const now = new Date();
const secondsAngle = now.getSeconds() * 6;
const minsAngle = now.getMinutes() * 6 + secondsAngle / 60;
const hourAngle = ((now.getHours() % 12) / 12) * 360 + minsAngle / 12;
以下是此计算的工作原理。
- 秒:我们取 60 秒并乘以
6
,结果是360
,正好是整个圆圈的角度数。 - 分:与秒相同,但现在我们添加秒的角度并将其除以
60
,以便在分钟内稍微增加角度,从而获得更精确的结果。 - 时:首先,我们计算小时的余数并将其除以
12
。 然后我们再次将余数除以12
以获得一个十进制值,我们可以将其乘以360
。 例如,当我们处于第 23 小时时,23 / 12 =
余数
11
。 将其除以 12,我们得到0.916
,然后将其乘以360
,总计330
。 在这里,我们将对分钟做与分钟相同的事情,添加分钟的角度,并将其除以12
,以获得更精确的结果。
现在我们有了角度,剩下的唯一事情就是通过在函数末尾添加以下内容来更新我们时钟的变量。
clock.style.setProperty("--second-hand-degrees", secondsAngle + "deg");
clock.style.setProperty("--minute-hand-degrees", minsAngle + "deg");
clock.style.setProperty("--hour-hand-degrees", hourAngle + "deg");
最后,我们将使用一秒钟的间隔触发该函数,以获得一个工作时钟。
const clock = document.getElementById("clock");
function setDate() {
// etc.
}
// Tick tick tick
setInterval(setDate, 1000);
setDate();
查看我们基本时钟的工作演示。
将其应用于圆锥渐变
好的,所以我们时钟的指针正在工作。 我们真正想要的是将它们映射到一个圆锥渐变,该渐变会随着时间的推移而更新。 如果您使用的是带有“渐变”表盘的 Apple Watch,您可能已经看到了相同的效果。

为此,让我们从使用圆锥渐变和两个自定义属性来更新 .clock
元素开始,这两个属性控制着起始角度和结束角度。
.clock {
/* same as before */
/* conic gradient vars */
--start: 0deg;
--end: 0deg;
/* same as before */
background:
conic-gradient(
from var(--start),
rgb(255 255 255) 2deg,
rgb(0 0 0 / 0.5) var(--end),
rgb(255 255 255) 2deg,
rgb(0 0 0 / 0.7)
);
}
您可以稍微调整一下,以按照您的喜好进行样式化。 我在渐变中添加了一些额外的颜色,但我喜欢这些颜色,只要您有起点和终点,就可以了。
接下来,我们将更新 setDate()
函数,以便它更新我们圆锥渐变的起始点和结束点的变量。 起始点将是我们的秒针,很容易找到,因为它将与我们分钟的角度相同。 要使它以小时针结束,我们应该使结束点与脚本中的 hourAngle
变量相同,但从其中减去起始点。
let startPosition = minsAngle;
let endPosition = hourAngle - minsAngle;
现在,我们可以再次使用 JavaScript 更新我们的变量。
clock.style.setProperty("--start", startPosition + "deg");
clock.style.setProperty("--end", endPosition + "deg");
看起来我们现在可以完成了,但有一个问题! 此计算只要分钟针的角度小于小时针的角度就能正常工作。 当分钟针越过它时,我们的圆锥渐变就会变得混乱。 为了解决这个问题,我们将使用负值作为起始点。 幸运的是,很容易发现何时出现这种情况。 在更新我们的变量之前,我们将添加以下内容。
if (minsAngle > hourAngle) {
startPosition = minsAngle - 360;
endPosition = hourAngle - startPosition;
}
通过从分钟角度减去 360
,我们能够为 startposition
变量设置一个负值。 由于这个负的起始点,我们的结束位置应该更新为小时角度减去起始位置。
好了,现在小时针和分钟针被设置为渐变角度。
就是这样! 但是不要让这阻止您进一步扩展它。 创建您自己的样式,并在评论中与我分享,以便我能查看它们。 以下是一些启发您的灵感。
我的分支
https://codepen.io/savostin/pen/bGMWybP
哦哦。 真是太酷了!
让我想起了这个时钟:https://www.bernhard-zacharia.com/donneruhren.aspx
非常棒!
应该注意的是,
setInterval
并不保证实际每 1000 毫秒执行一次,因为它会等待事件循环的下次迭代。 在类似的应用程序中,我使用了 500 毫秒的间隔,并在每次执行时都使用new Date()
读取设备时钟。我还在想是否可以(并且可靠地)只使用 JS 来设置初始时间,然后使用 CSS 动画计时来执行刻度。
抱歉,您可能已经知道这一点。 我错过了您确实在每次刻度时都使用了最新的
new Date()
读取。 尽管为了避免指针停滞,最好还是使用更短的间隔。我确实在每次刻度时都检查日期。 我想使用 CSS 动画可能是可以的,方法是使用线性计时。 这可能是一个有趣的事情,可以尝试一下 :) 但是,在这篇文章中,我的重点更多地放在渐变上。
哇,关于渐变的学习体验真棒,对我来说是一个新的主题,因为我已经离开了 HTM、CSS 和 JS 一段时间了(WordPress 支持妨碍了)。 以及 JS 复习。
感谢分享
很高兴你喜欢它:) 并欢迎您回到美丽的前端世界!