SVG使用Javascript平滑地将形状变形为其他预定义形状
- 我想要在形状之间平滑过渡(下面的示例显示了突然转变,以便您可以了解我需要平滑过渡的想法)。
- 形状的顺序由Javascript确定(例如,我固定了一个任意的顺序,但在实际问题中,用户输入决定选择哪个形状,所以事先不知道)。
example.svg
:SVG使用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>
如我在这里所做的那样,将所有值放入单个动画更容易。如果你不这样做,那么你必须开始每一个后续动画,因为前一个动画完成,这是可行的,但更复杂。
对于IE/Chrome,您需要fakeSmile或Chrome 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>
随着<animate>
的规则是,两个路径必须:
- 具有相同数目的路径元素的
- 具有匹配的路径命令
由于路径不兼容,您的动画将无法使用ible:
path-0: M h v h v
path-1: M h l l v
好。我知道一些命令是不兼容的,但并不是所有命令都是('h','v'和'l'毕竟是所有行)。修正了。尽管如此,它仍然不起作用(并且我听说过'
是的SMIL动画可能会被至少一些浏览器删除,而不是新的Web动画API。但是,第三方会提供polyfills来提供向后兼容性。 –
我在单独的动画中使用了它,因为单个动画片段的持续时间是可变的,我知道应该可以通过'来实现,但是我不能弄清楚我应该如何实现它,如果它在一个动画中。你可以修改你的答案,或者我应该问一个新的问题吗? –
user66554
您可以使用keyTimes来实现。如果你想要更多,请提出一个新问题。 –