Search code examples
svgsvg-animatesmil

SVG 'set' animation not looping as expected


I have a fairly simple SVG with 2 text elements. I want them to switch every 2 seconds (e.g. "2019", wait 2 seconds, "2020", wait 2 seconds, repeat forever).

For the life of me, nothing happens after the first "2019" is shown (e.g 2019 shows, then never goes away and 2020 never appears). If I change the show2019 begin to "3s;hide2020.end" it doesn't show up for 3 seconds, as expected, but still doesn't continue.

<?xml version="1.0" encoding="utf-8"?>
    <svg xmlns="http://www.w3.org/2000/svg" width="49" height="64">
        <rect x="0" y="0" width="49" height="64" rx="5" ry="5" stroke="#F00" fill="#FFF" stroke-width="1" />
            <text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" fill="#F00">
              <tspan x="50%" y="1em">Check</tspan>
              <tspan x="50%" y="2em">Terms</tspan>
              <tspan x="50%" y="3em">for</tspan>
            </text>
            <text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" font-weight="bold" fill="#F00" visibility="hidden">
              <tspan x="50%" y="4.5em">2019</tspan>
              <set id="show2019" attributeName="visibility" to="visible" dur="2s" repeatCount="123456" begin="0s;hide2020.end" />
              <set id="hide2019" attributeName="visibility" to="hidden" dur="2s" repeatCount="123456" begin="show2019.end + 2s" />
            </text>
            <text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" font-weight="bold" fill="#F00" visibility="hidden">
              <tspan x="50%" y="4.5em">2020</tspan>
              <set id="show2020" attributeName="visibility" to="visible"dur="2s" repeatCount="123456" begin="hide2019.end" />
              <set id="hide2020" attributeName="visibility" to="hidden" dur="2s" repeatCount="123456" begin="show2020.end + 2s" />
            </text>
    </svg>

CodePen


Solution

  • Well, I bring you an even nicer solution which resembles a path transformation. Instead of using set...attributeName I used animate...attributeName which allows you to do the same with better look and less code. See the code here:

        <svg xmlns="http://www.w3.org/2000/svg" width="49" height="64">
            <rect x="0" y="0" width="49" height="64" rx="5" ry="5" stroke="#F00" fill="#FFF" stroke-width="1" />
                <text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" fill="#F00">
                <tspan x="50%" y="1em">Check</tspan>
                <tspan x="50%" y="2em">Terms</tspan>
                <tspan x="50%" y="3em">for</tspan>
                </text>
                <text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" font-weight="bold" fill="#F00" opacity="1">
                    <tspan x="50%" y="4.5em">2019</tspan>
                        <animate attributeName="opacity" from="1" to="0" begin="0s" dur="3s" values="0;1;0" calcMode="linear" repeatCount="indefinite"/>
                </text>
                <text x="50%" text-anchor="middle" font-family="sans-serif" font-size="9pt" font-weight="bold" fill="#F00" opacity="1">
                    <tspan x="50%" y="4.5em">2020</tspan>
                        <animate attributeName="opacity" from="0" to="1" begin="0s" dur="3s" values="1;0;1" calcMode="linear" repeatCount="indefinite"/>
                </text>
        </svg>

    If you play around with the start duration and values can just adjust it as much as to meet your needs.