通过单击冻结 svg 动画

Freeze svg animation by click

我有这个 svg 代码可以生成 3 个改变颜色的矩形。我想通过单击这 3 个矩形中的任何一个来冻结它们,但我是 svg 的新手,我不知道该怎么做。我尝试使用 javascript,但没有用。有什么想法吗?

<svg width="500" height="500" onclick="freezing()">
  <rect x="10" y="20" width="90" height="60">
    <animate id="a1" attributeName="fill" from="red" to="blue" dur="3s" fill="freeze"  />
  </rect>
  <rect x="10" y="120" width="90" height="60">
    <animate id="a2" attributeName="fill" from="blue" to="yellow" dur="3s" fill="freeze"  />
  </rect>
  <rect x="10" y="220" width="90" height="60">
    <animate id="a3" attributeName="fill" from="yellow" to="green" dur="3s" fill="freeze" />
  </rect>
</svg>

将SVG中的SMIL动画与JavaScript结合起来真的很难。在这里,我用 JavaScript 中的 Animation 个对象替换了动画元素。动画对象有不同的方法,如 play()、pause() 和 cancel()。

通过调用Element.getAnimations()你可以获得一个元素上的所有动画。它是一个数组,所以你需要遍历它并暂停所有(在本例中只有一个)动画。

let timingoptions = {
  duration: 3000,
  fill: 'forwards'
};

document.querySelector('rect:nth-child(1)').animate([
  {fill: 'red'},
  {fill: 'blue'}
], timingoptions);

document.querySelector('rect:nth-child(2)').animate([
  {fill: 'blue'},
  {fill: 'yellow'}
], timingoptions);

document.querySelector('rect:nth-child(3)').animate([
  {fill: 'yellow'},
  {fill: 'green'}
], timingoptions);

document.querySelector('svg').addEventListener('click', e => {
  e.target.getAnimations().forEach(animation => animation.pause());
});
<svg width="500" height="500">
  <rect x="10" y="20" width="90" height="60"/>
  <rect x="10" y="120" width="90" height="60"/>
  <rect x="10" y="220" width="90" height="60"/>
</svg>

您可以使用 SVGSVGElement#pauseAnimations 方法暂停此元素内的 SMIL 动画 运行。 要恢复它,您可以调用 unpauseAnimations() 一个。

const svg = document.querySelector("svg");
svg.onclick = (evt) => {
  if (svg.animationsPaused()) {
    svg.unpauseAnimations();
  }
  else {
    svg.pauseAnimations();
  }
};
<svg width="500" height="500" >
  <rect x="10" y="20" width="90" height="60">
    <animate id="a1" attributeName="fill" from="red" to="blue" dur="3s" fill="freeze"  />
  </rect>
  <rect x="10" y="120" width="90" height="60">
    <animate id="a2" attributeName="fill" from="blue" to="yellow" dur="3s" fill="freeze"  />
  </rect>
  <rect x="10" y="220" width="90" height="60">
    <animate id="a3" attributeName="fill" from="yellow" to="green" dur="3s" fill="freeze" />
  </rect>
</svg>