SVG <set>标签的dur属性没有动画</set>

时间:2012-04-09 23:57:08

标签: css svg w3c

我正在尝试使用SVG <set>标记设置翻转动画,但即使我指定dur =“1s”,转换也是即时的(在Firefox,Safari,Opera和Chrome中)。

<html>
<body>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red">
        <set attributeType="CSS" attributeName="fill" to="green" begin="mouseover" end="mouseout" dur="1s" />
    </circle>
</svg> 

</body>
</html>

我可以达到我想要使用两个<animate>标签的效果,但我希望能够将转换应用于可能具有我想要保留的不同初始颜色的多个元素(此方法需要我指定第二个动画标签中的初始颜色“红色”。)

<html>
<body>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red">
        <animate attributeType="CSS" attributeName="fill" to="green" begin="mouseover" dur="1s" fill="freeze" />
        <animate attributeType="CSS" attributeName="fill" to="red" begin="mouseout" dur="1s" fill="freeze"/>
    </circle>
</svg> 

</body>
</html>

第一个代码段中的<set>标记会保留初始颜色,但转换不会设置动画。如果我对w3规范的理解是正确的,它应该是 - 这看起来像浏览器特定的错误,还是我误解了w3规范?有没有更好的方法来解决这个问题?

2 个答案:

答案 0 :(得分:3)

SVG 1.1 Specification

中所述
  

'set'元素提供了一种简单的方法仅设置属性在指定时间内的值
  ...
  to = "<value>"指定“set”元素持续时间内属性的值。

(强调我的。)

如您所见,duration元素的<set>不是转换时间,而是效果的应用时间。如果您移除end属性,您会看到颜色从红色变为绿色,持续1秒and then revert到原始值。

有关详细信息,请参阅SMIL Specification中的<set>元素。


编辑:以下是使用自定义数据注释SVG元素的示例,以及使用该数据创建所需<animate>元素的一次性运行脚本,基于填充的元素。您可以在http://phrogz.net/svg/change-color-on-hover.svg

直播查看此示例
<svg xmlns="http://www.w3.org/2000/svg" xmlns:y="yasashiku" viewBox="0 0 240 150">
  <title>Change Color on Hover</title>
  <style>
    circle { stroke:black; stroke-width:2px }
    circle:not([fill]) { fill:purple }
  </style>
  <circle cx="50"  cy="50"  r="40" fill="red"    y:hoverAnimFillTo="blue"  y:hoverAnimDur="0.3s" />
  <circle cx="100" cy="100" r="40" fill="red"    y:hoverAnimFillTo="green" y:hoverAnimDur="1s" />
  <circle cx="150" cy="42"  r="40" fill="orange" y:hoverAnimFillTo="yellow" />
  <circle cx="200" cy="100" r="40"               y:hoverAnimFillTo="steelblue" />
  <script>
    var els = document.getElementsByTagName('*'),
        y   = 'yasashiku';
    for (var i=els.length;i--;){
      var fillColor = els[i].getAttributeNS(y,'hoverAnimFillTo');
      if (fillColor){
        var dur = els[i].getAttributeNS(y,'hoverAnimDur') || '0.1s';
        createOn(els[i],'animate',{
          begin:'mouseover',
          attributeType:'CSS', attributeName:'fill',
          to:fillColor,
          dur:dur, fill:'freeze'
        });
        createOn(els[i],'animate',{
          begin:'mouseout',
          attributeType:'CSS', attributeName:'fill',
          to:els[i].getAttribute('fill') || computedStyle(els[i],'fill'),
          dur:dur, fill:'freeze'
        });
      }
    }
    function createOn(el,name,attrs){
      var e = el.appendChild(document.createElementNS(el.namespaceURI,name));
      for (var name in attrs) e.setAttribute(name,attrs[name]);
      return e;
    }
    function computedStyle(el,name){
      return document.defaultView.getComputedStyle(el,null)[name];
    }
  </script>
</svg>

答案 1 :(得分:2)

使用“values”和“KeyTimes”属性?

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red">
    <animate attributeType="CSS" attributeName="fill" values="red;green;green;red" keyTimes="0;0.2;0.8;1" begin="mouseover" dur="2s" fill="freeze" />
    <animate attributeType="CSS" attributeName="fill" to="red" begin="mouseout" dur="1s" fill="freeze"/>
  </circle>
</svg>