使用 Web Animations API 玩转粒子

Avatar of Louis Hoebregts
Louis Hoebregts

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

在运动和动画方面,可能没有什么比粒子更让我着迷了。因此,每次我探索新技术时,我最终都会创建尽可能多粒子的演示

在这篇文章中,我们将使用 Web Animations API 创造更多粒子的魔法,在点击按钮时创建烟花效果。

浏览器支持

在我撰写本文时,除了 Safari 和 Internet Explorer 之外,所有主要浏览器都至少部分支持 Web Animations API。Safari 支持可以在“实验性功能”开发者菜单中启用。

此浏览器支持数据来自 Caniuse,其中包含更多详细信息。数字表示浏览器在该版本及更高版本中支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
8475不支持8413.1

移动/平板电脑

Android ChromeAndroid FirefoxAndroidiOS Safari
12712712713.4-13.7

如果您有兴趣重现 Twitter 心形动画,还可以查看 这篇很棒的文章,作者是 Ana Tudor,这是另一个在按钮上爆炸粒子的绝佳示例。

HTML 设置

此演示不需要太多 HTML。我们将使用一个 <button> 元素,但它可以是其他类型的标签元素。如果我们真的想这样做,我们甚至可以监听页面上的任何点击,以使粒子从任何地方弹出。

<button id="button">Click on me</button>

CSS 设置

由于每个粒子都有一些共同的 CSS 属性,因此我们可以在页面的全局 CSS 中设置它们。由于您可以在 HTML 中创建自定义标签元素,因此我将使用 <particle> 标签名称来避免使用语义标签。但事实是,您可以动画化 <p><i> 或您选择的任何标签。

particle {
  border-radius: 50%;
  left: 0;
  pointer-events: none;
  position: fixed;
  top: 0;
}

这里需要注意两点

  • 粒子不应与我们页面的布局交互,因此我们正在设置一个 fixed 位置,topleft 均为 0px
  • 我们还删除了指针事件,以避免在 HTML 粒子显示在屏幕上时发生任何用户交互。

因为为按钮和页面布局设置样式并不是本文的目的,所以我将把这些放在一边。

JavaScript 设置

以下是我们将在 JavaScript 中遵循的六个步骤

  1. 侦听按钮上的点击事件
  2. 创建 30 个 <particle> 元素并将它们附加到 <body>
  3. 为每个粒子设置随机的 widthheightbackground
  4. 将每个粒子从鼠标位置动画到随机位置,同时淡出
  5. 动画完成后,从 DOM 中移除 <particle>

步骤 1:点击事件

// We first check if the browser supports the Web Animations API
if (document.body.animate) {
  // If yes, we add a click listener on our button
  document.querySelector('#button').addEventListener('click', pop);
}

步骤 2:粒子

// The pop() function is called on every click
function pop(e) { 
  // Loop to generate 30 particles at once
  for (let i = 0; i < 30; i++) {
    // We pass the mouse coordinates to the createParticle() function
    createParticle(e.clientX, e.clientY);
  }
}
function createParticle(x, y) {
  // Create a custom particle element
  const particle = document.createElement('particle');
  // Append the element into the body
  document.body.appendChild(particle);
}

步骤 3:粒子宽度、高度和背景

function createParticle (x, y) {
  // [...]
  // Calculate a random size from 5px to 25px
  const size = Math.floor(Math.random() * 20 + 5);
  // Apply the size on each particle
  particle.style.width = `${size}px`;
  particle.style.height = `${size}px`;
  // Generate a random color in a blue/purple palette
  particle.style.background = `hsl(${Math.random() * 90 + 180}, 70%, 60%)`;
}

步骤 4:动画化每个粒子

function createParticle (x, y) {
  // [...]
  // Generate a random x & y destination within a distance of 75px from the mouse
  const destinationX = x + (Math.random() - 0.5) * 2 * 75;
  const destinationY = y + (Math.random() - 0.5) * 2 * 75;

  // Store the animation in a variable because we will need it later
  const animation = particle.animate([
    {
      // Set the origin position of the particle
      // We offset the particle with half its size to center it around the mouse
      transform: `translate(${x - (size / 2)}px, ${y - (size / 2)}px)`,
      opacity: 1
    },
    {
      // We define the final coordinates as the second keyframe
      transform: `translate(${destinationX}px, ${destinationY}px)`,
      opacity: 0
    }
  ], {
    // Set a random duration from 500 to 1500ms
    duration: 500 + Math.random() * 1000,
    easing: 'cubic-bezier(0, .9, .57, 1)',
    // Delay every particle with a random value from 0ms to 200ms
    delay: Math.random() * 200
  });
}

因为我们有一个随机延迟,所以等待开始动画的粒子在屏幕的左上方可见。为了防止这种情况,我们可以在全局 CSS 中为每个粒子设置零不透明度。

particle {
  /* Same as before */
  opacity: 0;
}

步骤 5:动画完成后移除粒子

从 DOM 中移除粒子元素非常重要。因为我们在每次点击时都会创建 30 个新元素,所以浏览器的内存可能会很快填满并导致性能下降。以下是如何做到这一点

function createParticle (x, y) {
  // Same as before
  // When the animation is finished, remove the element from the DOM
  animation.onfinish = () => {
    particle.remove();
  };
}

最终结果

将所有内容整合在一起,就能得到我们想要的结果:五彩缤纷的粒子爆炸效果。

在演示中没有看到动画?检查您的浏览器是否支持 Web Animations API。请参阅文章顶部的支持表格。

发挥创意!

由于所有这些都使用 CSS,因此修改粒子样式非常简单。以下是用各种形状(甚至字符!)的五个示例。


或者,我们甚至可以像 Zach Saucier这篇文章 中那样,让按钮本身爆炸。

A button with a gradient exploding into particles