cssanimationsvgsmil

How do you add easing to an SVG SMIL animation?


I've been experimenting with the SMIL method for SVG animation, but I'm having trouble adding easing.

The animation shows a crosshair drawing a polygon.

Here's the working animation without easing:

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

<div>
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="100%"
        height="100%">

        <g id="crosshair_01" transform="translate(-15 -15)">
            <line x1="25" y1="15" x2="5" y2="15"
                style="fill:none;stroke:#005a84;stroke-miterlimit:10;stroke-width:2px" />
            <line x1="15" y1="5" x2="15" y2="25"
                style="fill:none;stroke:#005a84;stroke-miterlimit:10;stroke-width:2px" />
        </g>

        <path stroke-dasharray="1000" stroke="#58595B" pathLength="1000" fill="none" stroke-linejoin="round"
            stroke-dashoffset="1000" stroke-linecap="round" marker-start="url(#bm)" stroke-width="2" id="polygon_01"
            d="M 72.1 13.4 46.3 40.6 4.9 55.3 33 86.6 74.3 72.6 95.1 28.3 72.1 13.4" marker-end="url(#bm)" />


        <animate attributeName="stroke-dashoffset" fill="freeze" begin="0s; hidePolygon_01.end" from="1000"
            id="revealPolygon_01" dur="2s" xlink:href="#polygon_01" to="2000" />

        <animate attributeName="stroke-dashoffset" fill="freeze" begin="revealPolygon_01.end" from="0"
            id="hidePolygon_01" dur="2s" xlink:href="#polygon_01" to="1000" />

        <animateMotion xlink:href="#crosshair_01" begin="0s; hidePolygon_01.end" dur="2s" repeatCount="indefinite"
            additive="replace" calcMode="linear" keyTimes="0 ; 1" keyPoints="1 ; 0">
            <mpath xlink:href="#polygon_01" />
        </animateMotion>



    </svg>
</div>

And here I've tried to add easing using keyTimes and keySplines:

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

<div>
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="100%"
        height="100%">

        <g id="crosshair_01" transform="translate(-15 -15)">
            <line x1="25" y1="15" x2="5" y2="15"
                style="fill:none;stroke:#005a84;stroke-miterlimit:10;stroke-width:2px" />
            <line x1="15" y1="5" x2="15" y2="25"
                style="fill:none;stroke:#005a84;stroke-miterlimit:10;stroke-width:2px" />
        </g>

        <path stroke-dasharray="1000" stroke="#58595B" pathLength="1000" fill="none" stroke-linejoin="round"
            stroke-dashoffset="1000" stroke-linecap="round" marker-start="url(#bm)" stroke-width="2" id="polygon_01"
            d="M 72.1 13.4 46.3 40.6 4.9 55.3 33 86.6 74.3 72.6 95.1 28.3 72.1 13.4" marker-end="url(#bm)" />


        <animate attributeName="stroke-dashoffset" fill="freeze" begin="0s; hidePolygon_01.end" from="1000"
            id="revealPolygon_01" dur="2s" xlink:href="#polygon_01" to="2000" calcMode="spline" values="1000; 1332; 1498; 1664; 1830; 2000;" keyTimes="0; 0.16; 0.33; 0.49; 0.66; 0.83; 1;" 
            keySplines="0.42 0 1 1;
                0.42 0 1 1;
                0.42 0 1 1;
                0.42 0 1 1;
                0.42 0 1 1;
                0.42 0 1 1;" />

        <animate attributeName="stroke-dashoffset" fill="freeze" begin="revealPolygon_01.end" from="0"
            id="hidePolygon_01" dur="2s" xlink:href="#polygon_01" to="1000" />

        <animateMotion xlink:href="#crosshair_01" begin="0s; hidePolygon_01.end" dur="2s" repeatCount="indefinite"
            additive="replace" calcMode="linear" keyTimes="0 ; 1" keyPoints="1 ; 0">
            <mpath xlink:href="#polygon_01" />
        </animateMotion>



    </svg>
</div>

For some reason it makes the path disappear. Does anyone have any suggestions?

I've only tried adding easing to the first animation so far, I obviously want to get it working before I copy over to the others.


Solution

  • You had the wrong number of entries in your values attribute.

    For n splines, you need:

    You had only six entries in your values attribute. You needed seven.

    Also, the trailing semicolon you had in your lists is technically illegal. But I think the browsers are all forgiving with that. Correction: some browsers are.

    <div>
        <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="100%"
            height="100%">
    
            <g id="crosshair_01" transform="translate(-15 -15)">
                <line x1="25" y1="15" x2="5" y2="15"
                    style="fill:none;stroke:#005a84;stroke-miterlimit:10;stroke-width:2px" />
                <line x1="15" y1="5" x2="15" y2="25"
                    style="fill:none;stroke:#005a84;stroke-miterlimit:10;stroke-width:2px" />
            </g>
    
            <path stroke-dasharray="1000" stroke="#58595B" pathLength="1000" fill="none" stroke-linejoin="round"
                stroke-dashoffset="1000" stroke-linecap="round" marker-start="url(#bm)" stroke-width="2" id="polygon_01"
                d="M 72.1 13.4 46.3 40.6 4.9 55.3 33 86.6 74.3 72.6 95.1 28.3 72.1 13.4" marker-end="url(#bm)" />
    
    
            <animate attributeName="stroke-dashoffset" fill="freeze" begin="0s; hidePolygon_01.end" 
                id="revealPolygon_01" dur="2s" xlink:href="#polygon_01" calcMode="spline"
                values="1000; 1167; 1333; 1500; 1667; 1833; 2000"
                keyTimes="0; 0.16; 0.33; 0.49; 0.66; 0.83; 1" 
                keySplines="0.42 0 1 1; 0.42 0 1 1; 0.42 0 1 1; 0.42 0 1 1; 0.42 0 1 1; 0.42 0 1 1" />
    />
    
            <animate attributeName="stroke-dashoffset" fill="freeze" begin="revealPolygon_01.end" from="0"
                id="hidePolygon_01" dur="2s" xlink:href="#polygon_01" to="1000" />
    
            <animateMotion xlink:href="#crosshair_01" begin="0s; hidePolygon_01.end" dur="2s" repeatCount="indefinite"
                additive="replace" calcMode="linear" keyTimes="0 ; 1" keyPoints="1 ; 0">
                <mpath xlink:href="#polygon_01" />
            </animateMotion>
    
        </svg>
    </div>