使用圆锥渐变制作实时时钟

Avatar of Brecht De Ruyte
Brecht De Ruyte

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 价值 200 美元的免费积分!

渐变已经成为 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,您可能已经看到了相同的效果。

Black Apple Watch on a person's wrist showing a deep purple conic gradient face.
来源:Macworld

为此,让我们从使用圆锥渐变和两个自定义属性来更新 .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 变量设置一个负值。 由于这个负的起始点,我们的结束位置应该更新为小时角度减去起始位置。

好了,现在小时针和分钟针被设置为渐变角度。

就是这样! 但是不要让这阻止您进一步扩展它。 创建您自己的样式,并在评论中与我分享,以便我能查看它们。 以下是一些启发您的灵感。