Search code examples
htmlanimationsvgsvg-animate

SVG animate D coordinates, instantly changes instead of morphing


So I got an SVG shape:

<path id="shape" d="M1920,975c-611.4-49.2-866.7-298-946.6-602.2S682,0,682,0h1238V975z"/>

which I want to morph into this one:

<path id="shape" d="M1920 119 0 118 0 0 1920 0 1920 119z"/>

I tried to achieve that like this:

<path id="shape" d="M1920,975c-611.4-49.2-866.7-298-946.6-602.2S682,0,682,0h1238V975z"/>

<animate xlink:href="#shape"
    attributeName="d"
    attributeType="XML"
    from="M1920,975c-611.4-49.2-866.7-298-946.6-602.2S682,0,682,0h1238V975z"
        to="M1920 119 0 118 0 0 1920 0 1920 119z"
    dur="5s"
    fill="freeze"/>

But that just changes the shape instantly without any animation, instead of morphing like I wanted to.
Both shapes got the same amount of points (4), so that shouldn't be the problem, right?
Does anyone know what I did wrong?

body{
overflow:hidden;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 1920 1080">
<path id="shape" d="M1920,975c-611.4-49.2-866.7-298-946.6-602.2S682,0,682,0h1238V975z"/>

<animate xlink:href="#shape"
    attributeName="d"
    attributeType="XML"
    from="M1920,975c-611.4-49.2-866.7-298-946.6-602.2S682,0,682,0h1238V975z"
        to="M1920 119 0 118 0 0 1920 0 1920 119z"
    dur="5s"
    fill="freeze"/>
</svg>


Solution

  • It is not the points that have to match, but the path commands. Or, to state it another way: every letter has to reapear, and every number in the path string has to have an equivalent in each animation state. Only then intermediate states can be computed.

    You seem to want to transition to a shape with only sharp corners. That is in contrast to your source shape that uses the S smooth curveto command. A transition would include to change to another command, which is not possible.

    Reformulate the from path with a C cubic bezier command. (Adding a few spaces and commas to improve readability.) Instead of

    M 1920,975 c -611.4,-49.2 -866.7,-298 -946.6,-602.2 S 682,0 682,0 h 1238 V 975 z
    

    use

    M 1920,975 c -611.4-49.2 -866.7,-298 -946.6,-602.2 C 893.5,68.6 682,0 682,0 h 1238 V 975 z
    

    Then you can transition to

    M 1920,119 c 0,0 -1920-1 -1920-1 C 0 118 0,0 0,0 h 1920 V 119 z
    

    body{
    overflow:hidden;
    }
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
    	 viewBox="0 0 1920 1080">
    <path id="shape" d="M1920,975c-611.4-49.2-866.7-298-946.6-602.2S682,0,682,0h1238V975z"/>
    
    <animate xlink:href="#shape"
        attributeName="d"
        attributeType="XML"
        from="M 1920,975 c-611.4-49.2 -866.7-298 -946.6-602.2 C 893.5,68.6 682,0 682,0 h 1238 V 975z"
            to="M 1920,119 c0,0 -1920-1 -1920-1 C 0 118 0,0 0,0 h 1920 V 119z"
        dur="5s"
        fill="freeze"/>
    </svg>

    IF that does not look like you want it to, remember you can play around with the numbers, but not with the letters.