对角线条擦除动画

Avatar of Chris Coyier
Chris Coyier

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

前几天我在 Apple Arcade 上玩了一款名为 wurdweb 的游戏。 这是一款有趣的小游戏! 像在屏幕上四处走动的小形状人物(但除此之外什么也不做)这样的细微之处赋予了它很多个性。 我有点想要在网站上四处走动的小形状人物。 但另一个 UI 选择吸引了我的眼球,屏幕之间过渡的方式是这些对角线逐渐增长并填满屏幕,就像百叶窗关闭一样。

这是一个快速屏幕截图,展示了这些擦除的效果

我想尝试一下如何构建它。

我脑海中第一个想到的是 repeating-linear-gradient,以及如何 使用它来构建条纹。 所以,假设我们这样设置

.gradient {
  background-image:
    repeating-linear-gradient(
      45deg,
      #ff8a00,
      #ff8a00 10px,
      #e52e71 10px,
      #e52e71 20px
    );
}

这将为我们提供这样的条纹

但是,我们可以使用 transparent 作为颜色。 也就是说,如果我们用这样的条纹覆盖屏幕,我们就可以看到该颜色所在位置的透过部分。 就像这样

在该渐变定义中,我们将 10px 用作渐变的“开始”位置,将 20px 用作渐变的“结束”位置,然后再重复。 这里的部分技巧是保持该 20px 的“结束”位置不变,并动画化“开始”数字,使其达到该位置。 当我们这样做时,它实际上会用纯色覆盖屏幕。 问题是……如何对其进行动画化? 您无法执行以下操作

Screenshot of a CSS code snippet on a dark gray background with syntax highlighting. An arrow is pointing from the repeating linear gradient on the element to another repeating linear gradient inside keyframes. A note that says not going to animate is displayed in large white letters above a crying emoji.

我们需要做的是单独动画化该“开始”像素值数字。 我们可以使用 自定义属性,但这有点棘手,因为在没有声明它们的情况下,自定义属性只是字符串,而不是可动画化的长度。 因此,我们必须像这样执行此操作。

@property --start {
  syntax: "<length>";
  inherits: false;
  initial-value: 10px;
}
#cover {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-image: repeating-linear-gradient(
    45deg,
    #ff8a00,
    #ff8a00 var(--start),
    transparent var(--start),
    transparent var(--end, 20px)
  );
  animation: cover 1s linear infinite;
}
@keyframes cover {
  to {
    --start: 20px;
  }
}

我们必须 使用 @property 来执行此操作,我真的很喜欢这样做,但遗憾的是,它在浏览器中的支持有限。 不过,它确实有效! 我已经设置了所有内容,包括一个快速的 prefers-reduced-motion 媒体查询。 我使用了一点 JavaScript 在动画进行到一半(当屏幕被覆盖时)改变背景,以便您可以看到它可能如何用于屏幕过渡。 再次注意,这目前仅在基于 Chromium 的浏览器中有效

请注意,我也对其他内容使用了 CSS 自定义属性,例如条纹的角度和大小以及动画的速度。 它们都很容易更改! 我还加入了 knobs,以便您可以根据自己的喜好调整内容。 Knobs? 是的,它们很酷

点赞并订阅

整个事情 最初是一条推文。 在这种情况下,我很高兴我这样做,因为 Temani Afif 加入并提出了一种使用 mask 的方法,这意味着在所有浏览器中都有相当好的支持

我认为动画化背景颜色停止或遮罩位置的性能不太好,但由于我们在这里谈论的是“屏幕擦除”,所以可以想象,在页面过渡完成之前,页面不太可能被交互,因此也许这并不是什么大问题。