使用 SVG 和文本裁剪动画化文本块

Avatar of Zach Saucier
Zach Saucier

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

我在设计师的新闻通讯中偶然发现了这个简洁的小动画。 不幸的是,我忘记了来源,如果您认出它,请告诉我! 它是由 Martí Fenosa 制作的。

在动画中,一段文本似乎以色彩漩涡的形式逐渐出现,然后以相同的方式消失。这是一个流畅的效果,我想在代码中重现它。

我采用的方法是使用 SVG 文本作为 SVG 背景的剪辑路径。我们必须使用 SVG 文本,因为 CSS 目前仅允许我们在背景为 GIF 时使用文本裁剪来动画化背景,而我们不会这样做。

我们的首要任务是创建不同 SVG 形状的背景。椭圆形的斑点效果很好。需要注意的是,将您正在使用的任何插图应用程序中的画板/画布大小与您希望最终作品具有的 viewBox 的尺寸相匹配。(在 Inkscape 中,此选项位于文档属性的“缩放”部分。)

目标是用各种形状覆盖大部分画板。我发现如果一些形状重叠,看起来效果会更好。

接下来,我们将在 中创建一些文本,将构成背景的对象组合到 元素中,并在该组上应用 CSS clip-path。总的来说,它看起来像这样

  
  
    We are
    Creators
    +Innovators
  

  
  
    
    
  

此时,我们只会看到一些纯文本,因为我们还没有开始进行背景动画。

那么动画呢?我们可以使用像这样的相对简单的 CSS 动画

/* Animate the background shapes */
#background path {
  animation: pulse 4s cubic-bezier(0.455, 0.030, 0.515, 0.955) infinite;

  /* Necessary to keep the SVG objects in place while scaling */
  transform-origin: 50% 50%;
  transform-box: fill-box;
}

@keyframes pulse {
  /* Rotating it along with the scale makes it a little bit more fancy */
  0%, 100% { transform: scale(0) rotate(33deg); }
  35%, 65% { transform: scale(1) rotate(0deg); }
}

到目前为止,一切顺利。

transform-box: fill-box; 在 Internet Explorer 或 Edge 中目前不受支持,因此,如果您需要支持这些浏览器,则需要使用 JavaScript 解决方法,例如 此方法

查看 CodePen 上 Zach Saucier (@Zeaklous) 的 Pen
动画斑点 SVG 文本裁剪效果 - 第 1 部分

CodePen 上。

我们可以通过使用文本或矢量编辑器硬编码颜色值来开始绘制内容,但动态着色形状更有趣。像这样

// Define an array of colors
const colors = ['#f5a147','#51cad8','#112b39'];
// Select the SVG paths
var blobs = document.querySelectorAll("path");

// Randomly apply colors to the SVG fill property
blobs.forEach(blob => {
  blob.style.fill = colors[Math.floor(Math.random() * colors.length)];
});

为了更改每次迭代的文本值,我们首先需要将它们添加到 SVG 剪辑路径中。

  We are
  Creators
  +Innovators
  
  We are
  Movers
  +Shakers
  
  We are
  Stylish
  +Techy

然后,我们可以使用 CSS 或 JavaScript 以我们首选的顺序显示文本行。不幸的是,我们不能使用 元素包围 的每个部分,因为 元素不能在 clipPath 内部使用。对于这篇文章,我们将把内容拆分为三个 CSS 动画,每个动画对应三组路径

/* Selects paths 1-3 */
#textClip text:nth-of-type(n + 1):nth-of-type(-n + 3) {
  animation: showFirst 12s infinite;
}

/* Selects paths 4-6 */
#textClip text:nth-of-type(n + 4):nth-of-type(-n + 6) {
  animation: showSecond 12s infinite;
}

/* Selects paths 7-9 */
#textClip text:nth-of-type(n + 7):nth-of-type(-n + 9) {
  animation: showThird 12s infinite;
}

@keyframes showFirst {
  0%, 33% {
    opacity: 1;
  }
  33.0001%, 100% { opacity: 0; }
}

@keyframes showSecond {
  33.0001%, 66% {
    opacity: 1;
  }
  0%, 33%, 66.0001%, 100% { opacity: 0; }
}

@keyframes showThird {
  66.0001%, 99.999% {
    opacity: 1;
  }
  0%, 66%, 100% { opacity: 0; }
}

这样就搞定了!

查看 CodePen 上 Zach Saucier (@Zeaklous) 的 Pen
动画斑点 SVG 文本裁剪效果 - 第 2 部分

CodePen 上。

正如 Claus Colloseus 在评论中 指出的那样,上面和下面的演示在 Firefox 中不起作用,因为 CSS 蒙版规范 中存在歧义:“每个子元素的原始几何图形(不包括渲染属性,例如 clipPath 内部的填充、描边、描边宽度)从概念上定义了一个 1 位蒙版……它表示与该元素关联的图形的轮廓。”Firefox 忽略 clipPath 内部的任何不透明度更改,因此一次显示所有三个。另一方面,WebKit 在 clipPath 内隐藏不透明度为 0 的内容。在这种情况下谁是对的,我无权置评,但作为一种解决方法,我们应该使用 mask 以及一些 fill,而不是此处概述的 clipPath 方法。如更新的演示所示,基本方法相同,但 CSS 动画必须略微更改以适应蒙版的工作方式。

此时,我们可以玩得开心一点。例如,我们可以交换背景以获得不同的效果。我使用了 Inkscape 的星形工具(具有三到四个点)来生成一些随机形状(使用 Inkscape 的随机参数),然后使用来自众多 配色方案生成器 之一的调色板(我使用了 Palx)来生成此版本

查看 CodePen 上 Zach Saucier (@Zeaklous) 的 Pen
动画斑点 SVG 文本裁剪效果 - 第 3 部分

CodePen 上。

根据我们想要创建的效果,背景甚至不需要填充整个背景。例如,我们可以使用 元素复制文本,并使用该元素填充文本,如 此演示 中所示。

或者,我们可以通过像这样旋转背景斑点来混合它们

查看 CodePen 上 Zach Saucier (@Zeaklous) 的 Pen
动画斑点 SVG 文本裁剪效果 - 第 5 部分

CodePen 上。

为了使每组新单词的颜色发生变化,我们可以使用 CSS 或 JavaScript 进行动画。我使用了 JavaScript(并将隐藏文本行的 CSS 动画移动到 JavaScript 中)

查看 CodePen 上 Zach Saucier (@Zeaklous) 的 Pen
动画斑点 SVG 文本裁剪效果 - 第 6 部分

CodePen 上。

要水平居中文本,请将 x="50%" text-anchor="middle" 添加到每个 元素中 (演示)。由于我们使用的是多行格式,因此垂直居中需要更多的手动计算。

这种方法的一个优点是,由于它使用 SVG,因此默认情况下具有响应性!

附注:在我采用这种方法并寻找原始 GIF 作者时,我偶然发现了 Martí Fenosa 使用不同方法实现相同效果的 另一个重现。也请查看他的演示,因为它很巧妙!