Search code examples
svgsvg-animate

XML SVG - persist the end state of an animation


After the end of an AnimateTransform action, the element snaps back to the original value.
This isn't exactly unexpected as it's in the SMIL documentation:

As with all animation elements, this only manipulates the presentation value, and when the animation completes, the effect is no longer applied

But it is unwanted. I'd like to find a way to persist the changes using XML animations

Here's an example in SVG

<svg width="200" height="200" viewBox="0 0 100 100"
     xmlns="http://www.w3.org/2000/svg" 
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <rect id="outline" stroke="black" fill="white" 
        width="100" height="100" >
    <animateTransform id="one"
                      attributeType="XML"
                      attributeName="transform"
                      type="translate"
                      from="0" to="-7"
                      dur="1s" repeatCount="1" />
  </rect>
</svg>

One idea I had was to call a set action with dur="indefinite" that was triggered by the end of the first animation with begin="one.end", but can't quite seem to get the syntax right. I haven't found any documentation that show how to call set for a transformed value.

<svg width="200" height="200" viewBox="0 0 100 100"
     xmlns="http://www.w3.org/2000/svg" 
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <rect id="outline" stroke="black" fill="white" 
        width="100" height="100" >
    <animateTransform id="one"
                      attributeType="XML"
                      attributeName="transform"
                      type="translate"
                      from="0" to="-7"
                      dur="1s" repeatCount="1" />
    
    <!-- Doesn't work -->
    <set attributeType="XML"
         attributeName="transform"
         type="translate"
         to="-7" begin="one.end" /> 
    
    <!-- Does work (as POC) -->
    <set attributeType="css"
         attributeName="fill"
         to="green" begin="one.end" />

  </rect>
</svg>

This question on persisting the end state of the animation shows how to do this with css transforms by using -webkit-animation-fill-mode: forwards;, but that obviously won't have any affect on an svg animation


Solution

  • fill="freeze" will persist the state of an animation e.g.

    <svg width="200" height="200" viewBox="0 0 100 100"
         xmlns="http://www.w3.org/2000/svg" 
         xmlns:xlink="http://www.w3.org/1999/xlink">
      <rect id="outline" stroke="black" fill="white" 
            width="100" height="100" >
        <animateTransform id="one"
                          attributeType="XML"
                          attributeName="transform"
                          type="translate"
                          from="0" to="-7"
                          dur="1s" repeatCount="1"
                          fill="freeze"/>
      </rect>
    </svg>