2016-05-14 206 views
1
  • 我想要在形状之间平滑过渡(下面的示例显示了突然转变,以便您可以了解我需要平滑过渡的想法)。
  • 形状的顺序由Javascript确定(例如,我固定了一个任意的顺序,但在实际问题中,用户输入决定选择哪个形状,所以事先不知道)。

example.svgSVG使用Javascript平滑地将形状变形为其他预定义形状

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 

<svg xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    width="100%" height="100%" viewBox="0 0 400 400"> 
<script> 
window.animate = function(fromId, toId, next) 
{ 
    return function() 
    { 
     var elem = document.getElementById('elem'); 
     /* Here a smooth animation is supposed to happen. */ 
     elem.setAttribute('xlink:href', '#' + toId); 

     if(next) 
     { 
      window.setTimeout(next, 1000); 
     } 
    }; 
}; 

window.onload = function() 
{ 
    /* The animation order is determined by javascript. */ 
    var step3 = window.animate('path-2', 'path-1', null); 
    var step2 = window.animate('path-1', 'path-2', step3); 
    var step1 = window.animate('path-0', 'path-1', step2); 
    var step0 = window.animate('path-0', 'path-0', step1); 

    step0(); 
}; 
</script> 

<style>path{stroke:#000;}</style> 

<defs> 
<path id="path-0" style="fill:#fcc" d="M0,0 h100 v100 h-100 v-100" /> 
<path id="path-1" style="fill:#ccf" d="M0,0 h50 l50 50 l-100 50 v-100" /> 
<path id="path-2" style="fill:#cfc" d="M0,0 h150 l-50 50 l-100 50 v-100" /> 
</defs> 

<use id="elem" xlink:href="#path-0" x="150" y="150" /> 
</svg> 

据说它与<animate>某种程度上是可行的,但我不能得到它的工作。

animate.svg

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 

<svg xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    width="100%" height="100%" viewBox="0 0 400 400"> 
<script> 
window.set_animation = function(animId, fromId, toId) 
{ 
    var anim = document.getElementById(animId); 
    var from = document.getElementById(fromId); 
    var to = document.getElementById(toId); 
    anim.setAttribute('from', from.getAttribute('d')); 
    anim.setAttribute('to', to.getAttribute('d')); 
}; 

window.onload = function() 
{ 
    /* The animation order is determined by javascript. */ 
    window.set_animation('anim-0', 'path-0', 'path-1'); 
    window.set_animation('anim-1', 'path-1', 'path-2'); 
    window.set_animation('anim-2', 'path-2', 'path-1'); 

    /* Can start animation only once animation steps are defined. */ 
    var anim = document.getElementById('anim-0'); 
    anim.beginElement(); 
}; 
</script> 

<style>path{stroke:#000;}</style> 

<defs> 
    <path id="path-0" style="fill:#fcc" d="M0,0 l100,0 l0,100 l-100,0 l0,-100" /> 
    <path id="path-1" style="fill:#ccf" d="M0,0 l50,0 l50,50 l-100,50 l0,-100" /> 
    <path id="path-2" style="fill:#cfc" d="M0,0 l150,0 l-50,50 l-100,50 l0,-100" /> 
</defs> 

<path id="elem" x="150" y="150" d=""> 
    <animate id="anim-0" begin="indefinite" attributeType="XML" attributeName="d" dur="2s" from="[set by javascript]" to="[set by javascript]" /> 
    <animate id="anim-1" begin="anim-1.end" attributeType="XML" attributeName="d" dur="2s" from="[set by javascript]" to="[set by javascript]" /> 
    <animate id="anim-2" begin="anim-2.end" attributeType="XML" attributeName="d" dur="2s" from="[set by javascript]" to="[set by javascript]" /> 
</path> 
</svg> 

回答

1

如我在这里所做的那样,将所有值放入单个动画更容易。如果你不这样做,那么你必须开始每一个后续动画,因为前一个动画完成,这是可行的,但更复杂。

对于IE/Chrome,您需要fakeSmileChrome SMIL shim,但是在Firefox上没有插件的情况下播放。

<svg xmlns="http://www.w3.org/2000/svg" 
 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
 
    width="100%" height="100%" viewBox="0 0 400 400"> 
 
<script> 
 

 
function create_animation(animId, paths, attribute) 
 
{ 
 
    var anim = document.getElementById(animId); 
 
    var values = paths.map(function(item) { return document.getElementById(item).getAttribute(attribute) }).join(';'); 
 
     
 
    anim.setAttribute('values', values); 
 
} 
 

 
window.set_animation = function(animId, paths) 
 
{ 
 
    create_animation(animId, paths, 'd'); 
 
    create_animation(animId + '-colour', paths, 'fill'); 
 
}; 
 

 
window.onload = function() 
 
{ 
 
    /* The animation order is determined by javascript. */ 
 
    window.set_animation('anim-0', ['path-0', 'path-1', 'path-2']); 
 
}; 
 
</script> 
 

 
<style>path{stroke:#000;}</style> 
 

 
<defs> 
 
    <path id="path-0" fill="#fcc" d="M0,0 l100,0 l0,100 l-100,0 l0,-100" /> 
 
    <path id="path-1" fill="#ccf" d="M0,0 l50,0 l50,50 l-100,50 l0,-100" /> 
 
    <path id="path-2" fill="#cfc" d="M0,0 l150,0 l-50,50 l-100,50 l0,-100" /> 
 
</defs> 
 
    
 
<path> 
 
    <animate id='anim-0' dur="3s" attributeName='d' fill="freeze"/> 
 
    <animate id='anim-0-colour' dur="3s" attributeName='fill' fill="freeze"/> 
 
</path>

+0

我在单独的动画中使用了它,因为单个动画片段的持续时间是可变的,我知道应该可以通过'来实现,但是我不能弄清楚我应该如何实现它,如果它在一个动画中。你可以修改你的答案,或者我应该问一个新的问题吗? – user66554

+0

您可以使用keyTimes来实现。如果你想要更多,请提出一个新问题。 –

1

随着<animate>的规则是,两个路径必须:

  1. 具有相同数目的路径元素的
  2. 具有匹配的路径命令

由于路径不兼容,您的动画将无法使用ible:

path-0: M h v h v 
path-1: M h l l v 
+0

好。我知道一些命令是不兼容的,但并不是所有命令都是('h','v'和'l'毕竟是所有行)。修正了。尽管如此,它仍然不起作用(并且我听说过''将被丢弃?)。 – user66554

+0

是的SMIL动画可能会被至少一些浏览器删除,而不是新的Web动画API。但是,第三方会提供polyfills来提供向后兼容性。 –