动画颗粒纹理

Avatar of Geoff Graham
Geoff Graham

The DayTrip 网站 在其页面标题中使用了一种巧妙的效果,该效果使用动画的颗粒纹理扭曲背景图像。这种效果很微妙,但会营造一种尘土飞扬的复古氛围。

这种效果非常微妙。 您可以在右侧看到效果已启用,左侧看到效果已禁用,从而看到差异。

无效果(左)与颗粒效果(右)

我们可以用一张图像和一些 CSS 代码创建相同的效果。

步骤 1:设置

首先,让我们设置我们的页面标题。我们将使用一种常见的模式,其中背景图像占据整个空间。

.page-header {
  height: 100vh;
  background-image: url("/path/to/image.jpg");
}

以下是一个入门示例

查看 CodePen 上 Geoff Graham (@geoffgraham) 的 RpLKdx

步骤 2:选择纹理

接下来,我们需要一张具有颗粒纹理的图像。您可以自己创建。Subtle Patterns 还提供了许多不错的选择,包括我们将用于演示的 此选项。请注意,图像不必很大。大约 400px 的正方形即可。

我们的想法是将颗粒纹理覆盖在 .page-header 之上。我们可以使用 .page-header 上的 :after 伪元素,这样就不需要创建另一个元素了。

.page-header {
  height: 100vh;
  background-image: url("/path/to/image.jpg");
}

.page-header:after {
  /* content is required when using :after */
  content: "";
  /* The grainy image */
  background-image: url("/path/to/grainy/image.jpg");
  /* Specify a height and width above and beyond the page header for movement */
  height: 300%;
  width: 300%;
  /* We're using opacity in place of a transparent image */
  opacity: 0.3;
  /* We'll need this when the animation kicks in to hold the position of the texture */
  position: fixed;
}

请注意,我们还在伪元素上放置了 heightwidth 以及 topleft,以便它实际上超出页面标题的边界并居中。我们这样做是为了让颗粒纹理层有空间移动而不会暴露底部的页面标题层。这意味着我们的层排列方式如下

顶层现在超过了页面标题的边界

现在我们有一个不错的页面标题,上面覆盖着颗粒图像

查看 CodePen 上 Geoff Graham (@geoffgraham) 的 evGvKg

步骤 3:动画颗粒层

我们需要做的最后一件事是动画颗粒层。这是我们追求的效果,它为页面标题赋予了复古的模拟感。

DayTrip 网站使用以下内容来定义动画关键帧

@keyframes grain {
  0%, 100% { transform:translate(0, 0) }
  10% { transform:translate(-5%, -10%) }
  20% { transform:translate(-15%, 5%) }
  30% { transform:translate(7%, -25%) }
  40% { transform:translate(-5%, 25%) }
  50% { transform:translate(-15%, 10%) }
  60% { transform:translate(15%, 0%) }
  70% { transform:translate(0%, 15%) }
  80% { transform:translate(3%, 35%) }
  90% { transform:translate(-10%, 10%) }
}

很难直观地想象这段代码的含义,但它基本上是让顶部的颗粒层以锯齿形模式移动。以下是这种效果在更小范围内的图示

现在我们只需要将关键帧应用于 .page-header:after 即可看到它生效。我们将动画设置为播放 8 秒,并无限循环

.page-header:after {
  /* content is required when using :after */
  content: "";
  /* The animation */
  animation: grain 8s steps(10) infinite;
  /* The grainy image */
  background-image: url("/path/to/grainy/image.jpg");
  /* Specify a height and width above and beyond the page header for movement */
  height: 300%;
  width: 300%;
  /* We're using opacity in place of a transparent image */
  opacity: 0.3;
  /* We'll need this when the animation kicks in to hold the position of the texture */
  position: fixed;
}

整合

这是包含所有部分的完整代码片段。请注意,我们假设使用 Autoprefixer 进行所有供应商前缀添加。

.page-header {
  height: 100vh;
  background-image: url("/path/to/image.jpg");
}

.page-header:after {
  animation: grain 8s steps(10) infinite;
  background-image: url("/path/to/grainy/image.jpg");
  content: "";
  height: 300%;
  left: -50%;
  opacity: 0.3;
  position: fixed;
  top: -100%;
  width: 300%;
}

@keyframes grain {
  0%, 100% { transform:translate(0, 0) }
  10% { transform:translate(-5%, -10%) }
  20% { transform:translate(-15%, 5%) }
  30% { transform:translate(7%, -25%) }
  40% { transform:translate(-5%, 25%) }
  50% { transform:translate(-15%, 10%) }
  60% { transform:translate(15%, 0%) }
  70% { transform:translate(0%, 15%) }
  80% { transform:translate(3%, 35%) }
  90% { transform:translate(-10%, 10%) }
}

查看 CodePen 上 Geoff Graham (@geoffgraham) 的 动画颗粒效果