Xml 使用<;动画>;在SVG上,viewBox本身只工作两次

Xml 使用<;动画>;在SVG上,viewBox本身只工作两次,xml,animation,svg,smil,Xml,Animation,Svg,Smil,我一直在尝试使用SVG viewBox上的两个不同的s在大小之间循环,但尽管两个动画都独立工作,但如果第一个动画之后再次开始,第二个动画将不会运行。对我来说奇怪的是,第一个动画将继续运行,这表明它“识别”了另一个动画的结尾,即使它没有显示。如果我删除“small.end”,它甚至会按预期的方式运行……但这意味着它们不会一个接一个地重复 <svg viewBox = "0 0 300 300"> <animate id = "big" attributeName = "v

我一直在尝试使用SVG viewBox上的两个不同的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>


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

使用带有值数组的单个动画元素

<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>

迈克尔·穆拉尼的建议肯定是一种更容易做到这一点的方法,但值得进行更详细的检查:

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

Chrome(和其他webkit浏览器)中似乎发生的事情是,它让第一个动画的“冻结”值超过了第二个动画所做的任何更改。如果删除第一个动画上的“冻结”属性,则第二个动画的“冻结”值将阻止第一个动画显示

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

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

为了演示,如果我们添加了一个可能具有相加性的动画,例如颜色的变化,那么这两个动画将正确地相互替换,尽管设置为“冻结”:

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

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


至于如何同时处理这个问题:

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

由于您实际上并没有“冻结”两端的值,因此另一种方法是从两个端删除
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>

但是,如果要运行动画,将其冻结,然后在开始反向动画之前等待指定的时间,则这将不起作用。要让它发挥作用,你需要

  • 将其定义为具有多个值的单个动画,其中一些值重复两次以“冻结”该值,并为每个步骤指定关键帧时间;或者
  • 定义在每个过渡动画完成后开始的
    设置
    动画元素,并在设置的时间内保持指定的值,而不会无限期地将其冻结

哇,非常感谢!是否有方法延迟或选择何时在数组中的值之间移动?我编了这个例子,但我的实际项目的特点是在beginElement()调用上运行动画,所以如果我可以使用一个动画标记和一个像你这样的数组来来回移动,那将是令人惊讶的…@Ettubrutesbro:要设置
数组中每个转换使用的时间,请指定一个。要“保存”一个值,您需要在
values
数组中列出它两次,然后指定它“转换”到自身所需的时间。这是非常有用的-这是彻头彻尾的教育。非常感谢,阿梅里亚布!很高兴你发现它有用。我花了足够多的时间试图找出为什么它不起作用,我觉得我应该把它写出来。至少对于你要做的事情,有相当简单的变通选择。不知道你是否仍然在意,但你上面的小提琴在Chrome 42中工作(即重复)很好。@mrec有趣……谢谢你的提醒。