在 CSS 中动画 SVG 路径变化

Avatar of Chris Coyier
Chris Coyier

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

有时我会尝试使用<path>(SVG 的功能强大的绘图语法)绘制一些形状。我对它的所有功能只了解一部分,但我知道的足以造成一些危险。所有直线语法命令(如L)都非常简单,我发现曲线Q命令也很直观。将自己限制在一个viewBox="0 0 100 100"中,绘制简单的图形似乎并不那么糟糕。

这是一个我的经典示例,它使用所有基本命令绘制图形,同时也使用 CSS 对其进行动画处理(仅限 Chromium 浏览器)

奇怪但真实

<svg viewBox="0 0 10 10">
  <path d="M2,2 L8,8" />
</svg>
svg:hover path {
  transition: 0.2s;
  d: path("M8,2 L2,8");
}

前几天我遇到了一种情况,我需要一个 UI 元素,它根据其所处的状态显示不同的图标。它有点像“日志”形状,所以默认状态是直线,有点像汉堡菜单(只有四行,所以更像是文本行),然后是其他各种状态。

  1. 默认
  2. 活动
  3. 成功
  4. 错误

首先,我编写了世界上最复杂的有限状态机

const indicator = document.querySelector(".element");

let currentState = indicator.dataset.state;

indicator.addEventListener("click", () => {
  let nextState = "";

  if (currentState == "DEFAULT") {
    nextState = "ACTIVE";
  } else if (currentState == "ACTIVE") {
    nextState = "SUCCESS";
  } else if (currentState == "SUCCESS") {
    nextState = "ERROR";
  } else {
    nextState = "DEFAULT";
  }
  
  indicator.dataset.state = nextState;
  currentState = nextState;
});

这为使用数据属性设置样式状态打开了大门

.element {
  
  &[data-state="DEFAULT"] {
  }
  &[data-state="ACTIVE"] {
  }
  &[data-state="SUCCESS"] {
  }
  &[data-state="ERROR"] {
  }

}

因此,如果我的元素以四条线的默认状态开始

<div class="element" data-state="DEFAULT">
  <svg viewBox="0 0 100 100" class="icon">
    <path d="M0, 20 Q50, 20 100, 20"></path>
    <path d="M0, 40 Q50, 40 100, 40"></path>
    <path d="M0, 60 Q50, 60 100, 60"></path>
    <path d="M0, 80 Q50, 80 100, 80"></path>
  </svg>
</div>

……我可以在 CSS 中更改其他状态的路径。例如,我可以获取这四条直线并在 CSS 中更改它们。

请注意,四条“直线”中方便地包含了一个未使用的曲线点。只有在路径中具有相同数量和类型的点的路径才能在 CSS 中进行动画处理。放置曲线点打开了大门。

这四条新路径实际上绘制了一些接近圆形的东西!

.editor-indicator {
  
  &[data-state="ACTIVE"] {
    .icon {
      :nth-child(1) {
        d: path("M50, 0 Q95, 5 100,50");
      }
      :nth-child(2) {
        d: path("M100, 50 Q95, 95 50,100");
      }
      :nth-child(3) {
        d: path("M50,100 Q5, 95 0, 50");
      }
      :nth-child(4) {
        d: path("M0, 50 Q5, 5 50, 0");
      }
    }
  }

}

对于其他状态,我绘制了一个粗略的复选标记(用于成功)和一个粗略的感叹号(用于失败)。

这是一个演示(同样,Chromium),您可以单击它来更改状态

我最终没有使用它,因为 Firefox 和 Safari 都不支持 CSS 中的d: path();。并不是说它没有对它们进行动画处理,而是根本不起作用,所以对我来说它被淘汰了。我只是在不同的状态下替换了图标。

如果您需要跨浏览器形状变形,我们有一篇关于这方面的完整文章