单元素加载器:旋转器

Avatar of Temani Afif
Temani Afif

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

制作仅使用 CSS 的加载器是我最喜欢的任务之一。看着这些无限动画总令人满意。当然,还有很多技术和方法可以制作它们——无需去 CodePen 查看更多,您就能看到有多少种方法。不过,在本文中,我们将看到如何使用最少的代码制作单元素加载器。

制作了一系列超过 500 个单 div 加载器,在本系列的四篇文章中,我将分享我用来创建其中许多加载器的技巧。我们将涵盖大量的示例,展示微小的调整如何导致有趣的变化,以及需要编写多少代码才能实现这一切!

单元素加载器系列

  1. 单元素加载器:旋转器——您在此处
  2. 单元素加载器:圆点
  3. 单元素加载器:条形
  4. 单元素加载器:进入 3D

在第一篇文章中,我们将创建一个更常见的加载器模式:旋转条形

以下是方法

对该加载器进行简单实现的方法是,为每个条形创建一个元素,并将其包装在一个父元素中(总共九个元素),然后使用opacitytransform来获得旋转效果。

但是,我的实现只需要一个元素

<div class="loader"></div>

……以及 10 个 CSS 声明

.loader {
  width: 150px; /* control the size */
  aspect-ratio: 1;
  display: grid;
  mask: conic-gradient(from 22deg, #0003, #000);
  animation: load 1s steps(8) infinite;
}
.loader,
.loader:before {
  --_g: linear-gradient(#17177c 0 0) 50%; /* update the color here */
  background: 
    var(--_g)/34% 8%  space no-repeat,
    var(--_g)/8%  34% no-repeat space;
}
.loader:before {
  content: "";
  transform: rotate(45deg);
}
@keyframes load {
  to { transform: rotate(1turn); }
}

让我们分解一下

乍一看,代码可能看起来很奇怪,但您会发现它比您想象的要简单。第一步是定义元素的尺寸。在本例中,它是一个150px的正方形。我们可以使用aspect-ratio,这样无论元素的宽度如何,它都保持正方形。

.loader {
  width: 150px; /* control the size */
  aspect-ratio: 1; /* make height equal to width */
}

在构建 CSS 加载器时,我总是尝试为控制整体大小使用一个值。在本例中,它是width,我们将要介绍的所有计算都将参考该值。这使我能够更改单个值以控制加载器。始终能够轻松调整加载器的大小,而无需调整许多其他值,这一点至关重要。

接下来,我们将使用渐变来创建条形。这是最棘手的部分!让我们使用一个渐变来创建两个条形,如下所示

background: linear-gradient(#17177c 0 0) 50%/34% 8% space no-repeat;
Showing a space between two gradient lines for a single element loader.

我们的渐变是用一种颜色和两个颜色停止定义的。结果是纯色,没有淡出或过渡。大小等于34%宽和8%高。它也被放置在中心(50%)。技巧是使用关键字值space——这会复制渐变,使我们总共得到两个条形。

来自规范

图像会尽可能多次重复,以适合背景定位区域,且不会被剪裁,然后图像会间隔开以填充该区域。第一个和最后一个图像接触区域的边缘。

我使用的宽度等于34%,这意味着我们不能有超过两个条形(3*34%大于100%),但如果有两个条形,我们将有空隙(100% - 2 * 34% = 32%)。该空隙被放置在两个条形之间的中心。换句话说,我们使用一个宽度等于33%50%之间的渐变,以确保我们至少有两个条形,并且它们之间有一点空隙。值space会正确地将它们放置在我们想要的位置。

我们做同样的事情,再制作一个类似的渐变,以获得另外两个条形,分别位于顶部和底部,这会使我们的background属性值成为

background: 
 linear-gradient(#17177c 0 0) 50%/34% 8%  space no-repeat,
 linear-gradient(#17177c 0 0) 50%/8%  34% no-repeat space;

我们可以使用 CSS 变量对其进行优化,以避免重复

--_g: linear-gradient(#17177c 0 0) 50%; /* update the color here */
background: 
 var(--_g)/34% 8%  space no-repeat,
 var(--_g)/8%  34% no-repeat space;

所以,现在我们有四个条形,并且由于 CSS 变量,我们可以只编写一次颜色值,这使得以后很容易更新(就像我们对加载器大小所做的那样)。

为了创建剩余的条形,让我们利用.loader元素及其::before伪元素来获得另外四个条形,总共八个。

.loader {
  width: 150px; /* control the size */
  aspect-ratio: 1;
  display: grid;
}
.loader,
.loader::before {
  --_g: linear-gradient(#17177c 0 0) 50%; /* update the color here */
  background: 
    var(--_g)/34% 8%  space no-repeat,
    var(--_g)/8%  34% no-repeat space;
}
.loader::before {
  content: "";
  transform: rotate(45deg);
}

请注意使用display: grid。这使我们能够依靠网格的默认stretch对齐方式来使伪元素覆盖其父元素的整个区域;因此,我们无需在其上指定尺寸——另一个技巧可以减少代码量,并且避免我们处理大量值!

现在让我们将伪元素旋转45deg以定位剩余的条形。将鼠标悬停在以下演示上,以查看技巧

设置不透明度

我们要做的是创建一个印象,即有一个条形在圆形路径上移动时留下了逐渐消失的条形轨迹。现在我们需要使用 CSSmask和圆锥形渐变来操作条形的透明度,以创建该轨迹,如下所示

mask: conic-gradient(from 22deg,#0003,#000);

为了更好地查看技巧,让我们将其应用于一个全色框

红色的透明度以顺时针方向逐渐增加。我们将它应用于我们的加载器,我们就有了透明度不同的条形

Radial gradient plus, spinner bars equals spinner bars with gradients.

实际上,每个条形似乎都消失了,因为它们被渐变蒙版,并且位于两个半透明颜色之间。在运行时,这几乎是不可察觉的,因此可以说所有条形都具有相同的颜色,但透明度不同。

旋转

让我们应用旋转动画来获得我们的加载器。请注意,我们需要的是步进动画,而不是连续动画,这就是为什么我使用steps(8)的原因。8仅仅是条形的数量,因此可以根据条形的数量来更改该值。

.loader {
  animation: load 3s steps(8) infinite;
}

/* Same as before: */
@keyframes load {
  to { transform: rotate(1turn) }
}

就这样!我们只有使用一个元素和几行 CSS 代码就创建了加载器。我们可以通过调整一个值来轻松控制其大小和颜色。

由于我们只使用了::before伪元素,所以我们可以通过使用::after添加另外四个条形,总共 12 个条形,代码几乎相同

我们将伪元素的旋转更新为考虑30deg60deg,而不是45deg,同时使用 12 步动画,而不是 8 步动画。我还将高度减少到5%,而不是8%,以使条形更细一些。

另外,请注意我们在伪元素上使用了grid-area: 1/1。这使我们能够将它们放置在彼此相同的区域中,彼此堆叠。

猜猜看?我们可以使用另一种实现来获得相同的加载器

你能弄清楚代码背后的逻辑吗?以下是一个提示:不透明度不再使用 CSSmask来处理,而是使用渐变中的opacity属性来处理。

为什么不使用圆点代替呢?

我们完全可以这样做

如果您查看代码,您会发现我们现在使用的是径向渐变,而不是线性渐变。除此之外,概念完全相同,蒙版会创建一个透明度的印象,但我们将形状制作成圆形,而不是线条。

以下是说明新渐变配置的图形

Showing placement of dots in the single-element loader.

如果您使用的是 Safari,请注意演示可能存在错误。这是因为 Safari 目前不支持径向渐变中的at语法。但我们可以稍微重新配置渐变以克服此问题

.loader,
.loader:before,
.loader:after {
  background:
    radial-gradient(
      circle closest-side,
      currentColor 90%,
      #0000 98%
    ) 
    50% -150%/20% 80% repeat-y,
    radial-gradient(
      circle closest-side,
      currentColor 90%,
      #0000 98%
    ) 
    -150% 50%/80% 20% repeat-x;
}

更多加载器示例

以下是另一个类似于前一个的旋转器加载器创意。

对于此加载器,我只使用backgroundmask来创建形状(无需伪元素)。我还使用 CSS 变量定义配置,以便能够从同一代码创建许多变体——这是 CSS 变量功能的另一个示例。我写了另一篇关于此技术的文章,如果您想要了解更多详细信息。

请注意,一些浏览器仍然依赖于-webkit-前缀用于mask-composite,它有自己的一套值,并且不会在演示中显示旋转器。这里有一个方法可以做到这一点,无需使用mast-composite,以获得更多浏览器支持。

我还有另一个要给你。

对于这个,我使用background-color来控制颜色,并使用maskmask-composite来创建最终的形状。

Different steps for applying a master to a element in the shape of a circle.

在我们结束之前,这里有一些我之前制作的旋转加载器。我依赖于不同的技术,但仍然使用渐变、蒙版、伪元素等。它可以是一个很好的练习,以弄清楚每个加载器的逻辑,并同时学习新技巧。也就是说,如果你对它们有任何疑问,评论区就在下面。

总结

看看,我们可以用 CSS 做很多事情,只需要一个 div、几个渐变、伪元素和变量。看起来我们创建了很多不同的旋转加载器,但它们基本上都是同一件事,只是略有修改。

这仅仅是一个开始。在这个系列中,我们将研究更多关于创建CSS 加载器的想法和高级概念。

单元素加载器系列

  1. 单元素加载器:旋转器——您在此处
  2. 单元素加载器:圆点
  3. 单元素加载器:条形
  4. 单元素加载器:进入 3D