0

我一直在尝试在 SVG viewBox 上使用 2 个不同的 s 在大小之间循环,但是尽管两个动画都独立工作,但如果第一个动画在它之后再次开始,第二个动画将不会运行。对我来说奇怪的是,第一个会继续运行,表明它“识别”了另一个动画的结束,即使它没有显示。如果我删除“small.end”,它甚至会以它们应该的方式运行......但这意味着它们不会一个接一个地重复。

<svg viewBox = "0 0 300 300">
    <animate id = "big" attributeName = "viewBox" begin = "0;small.end" dur = "0.96s" from = "0 0 300 300" to = "0 0 650 390" fill = "freeze" />
    <animate id = "small" attributeName = "viewBox" begin = "big.end" dur = "0.96s" from = "0 0 650 390" to = "0 0 300 300" fill = "freeze" />
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>

http://jsfiddle.net/yXDZ2/

我一直在研究坐标系、加法和累积动画等各种东西,但似乎无法理解为什么会这样。我怀疑这可能是一个以某种方式“重置”动画状态的问题,但我有点超出我的深度 - 我不介意使用 javascript 或任何库来实现这一点。任何帮助或指示将不胜感激。谢谢!

4

2 回答 2

1

将单个动画元素与值数组一起使用。

<svg viewBox = "0 0 300 300">
    <animate attributeName = "viewBox" dur="1.92s" values="0 0 300 300; 0 0 650 390;0 0 300 300" fill="freeze"/>
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
于 2014-04-11T19:57:10.990 回答
1

Michael Mullany 的建议绝对是一种更简单的方法,但值得进行更详细的检查:

首先要提到的是,这个问题只发生在 Webkit/Blink 浏览器中;在 Firefox 中,您可以按预期获得弹跳动画。

Chrome(和其他 webkit 浏览器)中似乎发生的事情是,它让第一个动画的“冻结”值覆盖了第二个动画所做的任何更改。如果你去掉第一个动画的 freeze 属性,那么第二个动画的 freeze 值会阻止第一个动画的显示。

不是它应该如何工作的,影响相同属性的两个动画的默认行为是后面的动画应该比前面的动画具有更高的优先级。具体来说,SMIL 规范说:

不相加的较高优先级动画将覆盖所有较早(较低优先级)的动画,并简单地设置属性值。

问题似乎源于该additive属性(或至少指定 的选项additive="sum")仅适用于某些类型的动画属性:长度、颜色和矢量。它不适用于像“viewBox”这样的复杂属性。因此,webkit 浏览器似乎忽略了默认additive="replace"行为。

为了演示,如果我们添加一个可能是附加的动画比如颜色的变化,那么尽管有“冻结”设置,两个动画仍然可以正确地相互替换:

http://jsfiddle.net/yXDZ2/2/

但是,仅此一项并不能解释为什么如果第一个动画没有设置为在第二个动画结束后重新启动,那么为什么您的第二个动画可以正常工作。我的猜测是,这与 webkit 计算多个动画的“优先级”的方式中的错误有关。对于同时开始的多个动画,通过查看一个的开始时间是否依赖于另一个来确定优先级。但是,该计算不应该影响在不同时间开始的动画——在这种情况下,后面的动画应该总是优先的。

无论哪种方式,我都将其称为 webkit 实现中的错误。我在 webkit Bugzilla 上找不到任何相关的错误报告,如果找不到,您可能需要进行更彻底的搜索并提交问题。


至于在此期间如何处理问题:

正如建议的那样,您可以将两个动画组合成一个多值动画。这可能是最简单的方法并清理您的代码。

由于您实际上并没有“冻结”任一端的值,因此另一种执行您想要的操作的方法就是fill="freeze"从两者中删除参数:

<svg viewBox = "0 0 300 300">
    <animate id = "big" attributeName = "viewBox" begin = "0;small.end" 
             dur = "0.96s" from = "0 0 300 300" to = "0 0 650 390" />
    <animate id = "small" attributeName = "viewBox" begin = "big.end" 
             dur = "0.96s" from = "0 0 650 390" to = "0 0 300 300"  />
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>

http://jsfiddle.net/yXDZ2/1/

但是,如果您想运行动画、冻结它,然后在开始反向动画之前等待指定的时间,这将不起作用。为了让它工作,你需要要么

  • 将其定义为具有多个值的单个动画,其中一些重复两次以“冻结”该值,并为每个步骤指定关键时间;,
  • 定义set在每个过渡动画完成后开始的动画元素,并在设定的时间内保持指定的值,而不会无限期地冻结它。
于 2014-04-11T23:05:51.047 回答