Search code examples
javascriptreactjstypescriptsvgsvg-animate

SVG animate starts without being started


I have an inside a that starts without the variables being started:

<rect height={5} width={5}>
    <animate 
        attributeName="height" 
        from={5} to={10} dur="2s" 
        begin={start ? "0s": "indefinite}/></rect>

The component is inside a SVG which rerenders to change the 'start' variable to start the animation. However, the animation starts immediately regardless of when I choose to rerender it. So if I press it as soon as I render the page it's on then it will work properly. However, if I rerender the component after 2 seconds, the animation will jump to the end value. If I start the animation 1 second after rendering the page the component is on then the animation will play from the middle. What is going on?!

Thanks


Solution

  • begin and end times, if used without a reference to some other clock, always reference the beginning of the document. So instead of setting the value to 0s, you should use some other reference. Several possibilities come to mind:

    1. Start on click or some other event. The begin value takes the form of <id of event target element>.<event name>:

       <rect id="grafic" height={5} width={5}>
         <animate id="animation" attributeName="height"
                  from={5} to={10} dur="2s" begin="grafic.click"/>
       </rect>
      
    2. Start from some other code. The begin value stays at indefinite:

       <rect id="grafic" height={5} width={5}>
         <animate id="animation" attributeName="height"
                  from={5} to={10} dur="2s" begin="indefinite"/>
       </rect>
      

      but the animation is started by API call:

       document.getElementById('animation').beginElement();
      
    3. For a more React-like feeling, define a wallckock value of "right now" at the time of setting the attribute:

       const rightnow = () => new Date().toLocaleTimeString()
      
       <rect id="grafic" height={5} width={5}>
         <animate id="animation" attributeName="height"
                  from={5} to={10} dur="2s"
                  begin={start ? `wallclock(${rightnow()})` : "indefinite"/>
       </rect>