CSS 中的 Facebook 加载动画

Avatar of Fabrice Weinberg
Fabrice Weinberg 发布

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

以下内容是 Fabrice Weinberg 的客座文章。 我通过他在 CodePen 上的出色工作认识了 Fabrice。 他从看似任何地方汲取灵感,并通过 CSS 精心再现事物。 他给我发送了本教程,其中介绍了他重新创建他最受欢迎的 Pens 之一的技术,我很乐意发布! 我在这里学到了一些技巧。

大家好! CSS3 简直太棒了。 开发速度很快,可能性无穷。 今天,我想向您展示如何使用 CSS 中的多个背景图像和线性渐变制作一个很棒的动画。 我们将仅使用单个 HTML 元素来构建 Facebook 加载动画。

为简单起见,您将在 CSS 中看不到任何供应商前缀。 在我们深入创建 Facebook 加载动画之前,我将解释基本技术。

background-image

我们都知道 background-image 属性。 您提供指向外部图像文件(或数据 URI)的 url(),以使该图像显示为任何 HTML 元素的背景。

现在,可以使用 linear-gradientradial-gradient 作为背景图像。 这开辟了全新的背景世界,这些背景可以使用代码生成。 我不会解释语法(您可以从前两个链接中获取),但我将为您提供一些技巧,这些技巧将帮助您创建很棒的图案和几乎任何形状。

最有用的技巧是可以一次添加多个背景图像。

div {
  background-image: 
    background-image
    [, background-image]* /* optional additional backgrounds */
}

有关更多信息,请参阅 MDN:background-image。 要查看其他人使用这些属性创建的内容,请查看此 画廊

如何使用线性渐变绘制

让我们从一些基本的线性渐变开始,以了解其语法。

background-image: linear-gradient(90deg, blue, red);

要查看语法及其所有可能性,您应该查看 MDN:linear-gradient

这将产生以下结果

您会看到蓝色和红色之间有一个不错的渐变。 但总是绘制渐变会相当无聊。 如果能够生成像这样的图案,那不是很好吗?

sharpcolor

所以让我们开始吧! 看看上面的图案。 您会看到四种不同的颜色,每种颜色需要 1/4 的宽度。 用百分比表示,我们得到 25%(100%/4)。 对于这种简单的图案,我建议您使用百分比,这样图案会动态适应元素的大小。

要将图像图案转换为 linear-gradient,我们将从最左边的颜色开始。 在这种情况下为蓝色。

background-image: linear-gradient(90deg, blue 25%);

这将导致一个空白背景图像。 要使 linear-gradient 工作,我们必须添加至少两种颜色。 让我们添加下一种颜色,绿色

background-image: linear-gradient(90deg, blue 25%, green 25%);

第一个颜色值很特殊,因为“蓝色 25%”并不意味着蓝色从 25% 开始。 在这种情况下,“蓝色 25%”意味着蓝色扩展到 25%。

我们得到的是

正是我们想要的,蓝色和绿色之间的清晰分离。 但是您可能已经注意到,我们必须为蓝色和绿色都编写 25%。 在开发过程中,这非常烦人,因为您必须更改这两个值以保持清晰的分隔。

在使用线性渐变时,我发现了一种很好的方法,可以使这一过程变得更轻松

background-image: linear-gradient(90deg, blue 25%, green 0);

现在,我们只需将绿色的位置设置为“0”。 我们通过这种方式实现的是,绿色将始终从与前一种颜色(在本例中为蓝色)完全相同的位置开始。 结果与之前相同,但现在您只需更改一个值即可更改蓝色矩形的大小。 添加剩余的颜色变得非常容易,因为我们现在知道如何创建清晰的颜色切割。

background-image: linear-gradient(90deg, blue 25%, green 0, green 50%, red 0, red 75%, yellow 0);

您现在可以了解为什么第一个颜色值很特殊。 对于每种其他颜色,我们必须将其定义两次。 一次用于起始位置,另一次用于指定其扩展范围。

结果

我们如何创建形状?

要使用 background-image 属性创建一些基本形状,我们将从以下内容开始

.squareandcircle{
  width: 40px;
  height: 30px; 
  background-image: linear-gradient(90deg, blue, blue),
                    radial-gradient(center, circle, green 10px, transparent 0);

  background-size: 15px 15px,
                   20px 20px;

  background-position: 0    0,
                       20px 10px;

  background-repeat:no-repeat;
}

squareandrect

我们使用了多个背景图像,并结合了 background-sizebackground-position 来创建正方形和圆形。

它是如何工作的?

从 background-image 开始

首先,我们必须创建背景图像。 为简单起见,我们使用最基本的 linear-gradient 和最基本的 radial-gradient

现在转到下一个属性:background-size

background-size 属性将为之前创建的每个背景图像设置大小,顺序与创建顺序相同。

因此,在我们的例子中,线性渐变的大小为 15x15px。 对于径向渐变,它为 20x20px。

每个背景的位置:background-position

现在,我们有两个图像,一个是大小为 15x15px 的正方形,一个是适合 20x20px 正方形的圆形。 但这些图像彼此重叠。 要移动它们,我们需要 background-position

对于 background-position,我们必须为每个背景图像定义相对于元素左上角的偏移量。

这里,第一个图像(正方形)将在左上角,圆形将比它向左 20px,向下 20px。 请记住,我们从元素的左上角移动每个图像。

background-repeat

最后一个未解释的部分是 background-repeat,这很简单。 我们不希望生成的图像在任何方向上重复,因此我们将其设置为 no-repeat。 如果我们只为它添加一个值,则该值将被我们创建的所有背景图像使用。

那么我们如何使用它来制作动画?

很简单。 我们使用背景图像创建形状,然后使用 animation 属性通过更改背景大小和/或位置来为整个内容设置动画。

在进行 Facebook 加载动画之前,我们先来看一个简单的示例。 我们从一些基本的标记开始,如下所示

.square {
  width: 40px;
  height: 30px; 
  background-color: gray;
  background-image: linear-gradient(90deg, blue, blue);
  background-size: 15px 15px;
  background-position: 0 0;
  background-repeat: no-repeat;
}

看起来像

rect

让我们分六个步骤为它设置动画,将正方形从右上角移动到右下角,再移动到左下角。

基本数学告诉我们,我们每帧需要 16.6% 的时间(100%/6 ~ 16.6%)才能完成关键帧动画。 在每帧中,我们修改背景位置,以营造正方形移动的错觉。

最终我们将得到相当多的 CSS 代码

@keyframes move {
    16.6% {
      background-position: 0 0;
    }
    33.2% {  
      background-position: 12.5px 0;
    }
    49.8% {
      background-position: 25px 0;
    }
    66.4% {
      background-position: 25px 15px;        
    }
    83% {
      background-position: 12.5px 15px;      
    }
    99% { 
      background-position: 0 15px;               
    }
}

要查看动画,我们必须像这样将动画添加到正方形元素中

.square{
  width: 40px;
  height: 30px; 
  background-color: gray;
  background-image: linear-gradient(90deg, blue, blue);
  background-size: 15px 15px;
  background-position: 0 0;
  background-repeat: no-repeat;

  animation: move 1s steps(1, start) infinite;
}

steps 函数很棒。 您可以在 此处 阅读有关它的更多信息。

查看实际效果


您在这里看到的嵌入式动画可能已停止,要查看动画,请访问 Pen

尝试玩弄它以理解您拥有的所有可能性。事实上,我们这里得到的是一个开放的画布,我们可以在上面绘制几乎所有形状并以任何方式对其进行动画处理。

Facebook 加载动画。

现在是时候使用这些技术制作一些更复杂的动画了。

看看 Facebook 加载动画的原始 GIF。

orig-loading

在 GIF 中,我们看到垂直条纹从左到右移动,同时收缩并失去颜色。

我们如何在 CSS 中存档?让我先说一下:我不会解释如何创建所有这些条纹中的每一个。我只会解释如何创建第一个,从那里开始,理解其余部分应该不难。

让我们放大第一个条纹。

zoomedstripe

第一个形状是 4 像素宽,16 像素长。一个 3x16 像素的实心彩色矩形周围有一个 1 像素的边框。为简单起见,我们将创建的边框也将具有实心颜色。要创建这样的形状,我们必须使用linear-gradient 生成两个背景图像。一个用于左侧边框、实心内部矩形和右侧边框,另一个用于上边框和下边框。我们从用于左侧边框、实心内部矩形和右侧边框的linear-gradient 开始。

#facebook {
  width: 16px;
  height: 16px;    

  background-image: linear-gradient(90deg, #8490c6 1px, #aeb5da 0, #aeb5da 3px, #8490c6 3px);  
  background-size: 4px 16px;
  background-position: 0 0;

  /* Just to make it a little bigger*/
  zoom: 5; 
}

结果

cssstripe1

要完成此形状,我们必须添加另一个背景图像来创建上边框和下边框。

#facebook {
  width: 16px;
  height: 16px;    
  background-image:
            linear-gradient(0deg, #8490c6 1px, transparent 0, transparent 15px, #8490c6 15px),
            linear-gradient(90deg, #8490c6 1px, #aeb5da 0, #aeb5da 3px, #8490c6 3px);      

  background-size: 4px 16px,
                   4px 16px;

  background-position: 0 0,
                       0 0;

  background-repeat: no-repeat;

  /* Just to make it a little bigger*/
  zoom:5;
}

没有必要重复background-sizebackground-position 的值,因为它们是相同的,但为了进一步开发,最好写下来。

现在我们有了这个

cssstripe2

我们需要制作六个这样的条纹,颜色和尺寸稍微小一些。现在应该清楚如何制作这些条纹了。

#loader {
    zoom: 1; /* Increase this for a bigger symbol*/
    width: 16px;
    height: 16px;

    background: linear-gradient(0deg, #f4f5fa 1px, transparent 0, transparent 8px, #f4f5fa 8px),   /* 6  */
                linear-gradient(90deg, #f4f5fa 1px, #f6f9fb 0, #f6f9fb 3px, #f4f5fa 3px),

                linear-gradient(0deg, #ececf5 1px, transparent 0, transparent 8px, #ececf5 8px),   /* 5  */
                linear-gradient(90deg, #ececf5 1px, #f2f3f9 0, #f2f3f9 3px, #ececf5 3px),

                linear-gradient(0deg, #e7eaf4 1px, transparent 0, transparent 8px, #e7eaf4 8px),   /* 4  */
                linear-gradient(90deg, #e7eaf4 1px, #eef1f8 0, #eef1f8 3px, #e7eaf4 3px),

                linear-gradient(0deg, #b9bedd 1px, transparent 0, transparent 10px, #b9bedd 10px), /* 3  */
                linear-gradient(90deg, #b9bedd 1px, #d0d5e8 0, #d0d5e8 3px, #b9bedd 3px),

                linear-gradient(0deg, #9fa6d2 1px, transparent 0, transparent 15px, #9fa6d2 15px), /* 2  */
                linear-gradient(90deg, #9fa6d2 1px, #c0c5e1 0, #c0c5e1 3px, #9fa6d2 3px),

                linear-gradient(0deg, #8490c6 1px, transparent 0, transparent 15px, #8490c6 15px), /* 1  */
                 linear-gradient(90deg, #8490c6 1px, #aeb5da 0, #aeb5da 3px, #8490c6 3px); 
  
    background-repeat: no-repeat;

    background-size: 
               4px 9px,   /* 6 */
               4px 9px,

               4px 9px,   /* 5 */
               4px 9px,

               4px 9px,   /* 4 */
               4px 9px,

               4px 11px,  /* 3 */
               4px 11px,

               4px 16px,  /* 2 */
               4px 16px,

               4px 16px,  /* 1 */
               4px 16px;

  background-position-x: -4px; /* Hide All */
  background-position-y: 3px, 3px, 3px, 3px, 3px, 3px, 2px, 2px, 0, 0, 0, 0;
}

所有六个条纹都隐藏了,因为它们在 x 轴上移动了 -4 像素。

让我们再次想想原始的 GIF。它包含八个步骤,将每个条纹进一步向左移动。因此,我们需要制作一个包含八个步骤的动画,而每个步骤需要 12.5% 的时间(100%/8)。在每一步中,每个条纹都会向右移动 6 像素。如果条纹在 x 轴上的位置大于 16 像素,它就会超出画布,我们可以将其放置在 -4 像素处将其隐藏。

您可能已经注意到 background-position-y 的使用。这为我们节省了很多代码,因为我们只需要在 x 轴上移动条纹,我们永远不必更改 y 坐标,因此我们只需要在关键帧动画中写入 x 轴位置的坐标。

@keyframes wait {
  12.5% {
    background-position-x: -4px,-4px,   -4px, -4px,  -4px,-4px,
                           -4px,-4px,   -4px, -4px,   0,   0;
  }
  25% {
    background-position-x: -4px, -4px,  -4px, -4px,  -4px,-4px,
                           -4px, -4px,   0,    0,     6px, 6px;
  }
  37.5% {
    background-position-x: -4px, -4px,  -4px, -4px,  -4px, -4px,
                            0,    0,     6px,  6px,  12px, 12px;
  }
  50%{
    background-position-x: -4px, -4px,  -4px, -4px,   0,    0,
                            6px,  6px,  12px, 12px,  -4px, -4px;
  }
  62.5% {
    background-position-x: -4px, -4px,   0,    0,     6px,  6px,
                           12px, 12px,  -4px, -4px,  -4px, -4px;
  }
  75% {
    background-position-x:  0,    0,     6px,  6px,  12px, 12px,
                           -4px, -4px,  -4px, -4px,  -4px, -4px;
  }
  87.5%{
    background-position-x:  6px,  6px,  12px, 12px,  -4px, -4px,
                           -4px, -4px,  -4px, -4px,  -4px, -4px;
  }
  100% {
    background-position-x: 12px, 12px,  -4px, -4px,  -4px, -4px,
                           -4px, -4px,  -4px, -4px,  -4px, -4px;
  }
}

因为每个条纹都由两个背景图像组成,所以我们必须在每一步中更改 12 个背景位置(每个条纹两个)。

最后,我们可以将动画属性添加到我们的元素中。

animation: wait .80s steps(1, start) infinite;

以下是 Codepen 上的实时演示

同样,您在这里看到的嵌入式动画可能已停止,要查看动画,请访问 Pen

感谢您的阅读。希望你喜欢。谢谢!