How do you add easing to an SVG SMIL animation?

Viewed 184

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.

1 Answers

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

For n splines, you need:

  • n+1 values entries
  • n+1 keyTimes entries
  • n keySplines entries

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>

Related