svgsvg-animatesvg.js

How to change the start point of SVG animateMotion?


I'm trying to change the start point of the animation which can be seen at https://codepen.io/anon/pen/vdmMOJ.

The problem is: How can I make the blue circle start from its own position instead of it snapping to another position and then the animation starts?

<svg width="500px" height="100%" viewBox="-500 -500 1500 1500">

  <defs id="SvgjsDefs1225"></defs>
  <path id="SvgjsPath1226" d="
                    M 397.0000000000009, -60
                    m -348, 0
                    a 348,348 0 1, 0 696,0
                    a 348,348 0 1, 0 -696,0
                " fill="none" stroke="#c9e3ff" stroke-width="12"></path>

  <g id="SvgjsG1234" class="circleFive">
      <circle id="SvgjsCircle1243" r="34.6" cx="215.5" cy="231.6" fill="#022549" cursor="pointer"></circle>
      <path id="SvgjsPath1244" d="M28,38.92A10.59,10.59,0,0,0,32.83,40c2,0,3.5-1.18,3.5-3s-1.64-3-4-3a10.83,10.83,0,0,0-4,.71l.5-12.46H41V27H33.73l-.12,3.29a6,6,0,0,1,1.33-.12c4.19,0,7.25,2.91,7.25,7.53S38.69,45,33.61,45A11.4,11.4,0,0,1,28,43.79Z" transform="matrix(1, 0, 0, 1, 181.136, 199.592)" cursor="pointer" fill="white"></path>
    
      <animateMotion dur="4s" path="M181.50000762939544 -291.6000061035156M-166.49999237060456 -291.6000061035156A348 348 0 1 0 529.5000076293954 -291.6000061035156A348 348 0 1 0 -166.49999237060456 -291.6000061035156" begin="click" fill="freeze" calcMode="linear" keyTimes="0;1" keyPoints="1;0" repeatCount="1"></animateMotion>

 </g>

</svg>


Solution

  • When using motion paths, it's always a lot easier if you make it start at (0,0). That way removes a lot of the semi-complicated arithimetic needed to compensate for the difference between the animated element and the motion path.

    Let's start by pretending the dot is on the LHS (the 9 o'clock position). The motion path would be like this:

    <svg width="500px" height="100%" viewBox="-500 -500 1500 1500">
      
      <defs id="SvgjsDefs1225"></defs>
      <path id="SvgjsPath1226" d="
                        M 397.0000000000009, -60
                        m -348, 0
                        a 348,348 0 1, 0 696,0
                        a 348,348 0 1, 0 -696,0
                    " fill="none" stroke="#c9e3ff" stroke-width="12"></path>
    
      <g id="SvgjsG1234" class="circleFive">
          <circle id="SvgjsCircle1243" r="34.6" cx="215.5" cy="231.6" fill="#022549" cursor="pointer"></circle>
          <path id="SvgjsPath1244" d="M28,38.92A10.59,10.59,0,0,0,32.83,40c2,0,3.5-1.18,3.5-3s-1.64-3-4-3a10.83,10.83,0,0,0-4,.71l.5-12.46H41V27H33.73l-.12,3.29a6,6,0,0,1,1.33-.12c4.19,0,7.25,2.91,7.25,7.53S38.69,45,33.61,45A11.4,11.4,0,0,1,28,43.79Z" transform="matrix(1, 0, 0, 1, 181.136, 199.592)" cursor="pointer" fill="white"></path>
        
          <animateMotion dur="4s" 
            path="M 0, 0
                  a 348,348 0 1, 0 696,0
                  a 348,348 0 1, 0 -696,0"
            begin="click" fill="freeze" calcMode="linear" keyTimes="0;1" keyPoints="1;0" repeatCount="1"></animateMotion>
          
     </g>
          
    </svg>

    But instead, you've positioned it at some other point on the circle. We need to work out the angle in order to calculate the new motion path.

    The dot is at (215.5, 231.6). The centre of the blue circle is at (397, -60). Therefore relative to the centre, the dot is at (-181.5, 291.6).

    Now we know that, we also know that the opposite side of the motion path circle is at 181.5, -291.6. So we can update the motion path with that info. The values for the motion path arc (a) commands will be double those coord values (363 and 583.2).

    <svg width="500px" height="100%" viewBox="-500 -500 1500 1500">
      
      <defs id="SvgjsDefs1225"></defs>
      <path id="SvgjsPath1226" d="
                        M 397.0000000000009, -60
                        m -348, 0
                        a 348,348 0 1, 0 696,0
                        a 348,348 0 1, 0 -696,0
                    " fill="none" stroke="#c9e3ff" stroke-width="12"></path>
    
      <g id="SvgjsG1234" class="circleFive">
          <circle id="SvgjsCircle1243" r="34.6" cx="215.5" cy="231.6" fill="#022549" cursor="pointer"></circle>
          <path id="SvgjsPath1244" d="M28,38.92A10.59,10.59,0,0,0,32.83,40c2,0,3.5-1.18,3.5-3s-1.64-3-4-3a10.83,10.83,0,0,0-4,.71l.5-12.46H41V27H33.73l-.12,3.29a6,6,0,0,1,1.33-.12c4.19,0,7.25,2.91,7.25,7.53S38.69,45,33.61,45A11.4,11.4,0,0,1,28,43.79Z" transform="matrix(1, 0, 0, 1, 181.136, 199.592)" cursor="pointer" fill="white"></path>
        
          <animateMotion dur="4s" 
            path="M 0, 0
                  a 348,348 0 1, 0 363, -583.2
                  a 348,348 0 1, 0 -363, 583.2"
            begin="click" fill="freeze" calcMode="linear" keyTimes="0;1" keyPoints="1;0" repeatCount="1"></animateMotion>
          
     </g>
          
    </svg>

    But uh oh. The motion path is wonky now. It bulges. What caused that? The answer is that the coords we used for the dot (-181.5, 291.6) are not exactly on the circle. We can check by calculating what radius those values would correspond to.

    r = sqrt(-181.5^2 + 291.6^)
      = 343.47
    

    Which is different from the radius of our circle (348). We can fix that by scaling our coordinate values up by the ratio (348 / 343.47)

    The new coordinates are now (183.9, 295.4). If we use those values, instead, to update our motion math, we get:

    <svg width="500px" height="100%" viewBox="-500 -500 1500 1500">
      
      <defs id="SvgjsDefs1225"></defs>
      <path id="SvgjsPath1226" d="
                        M 397.0000000000009, -60
                        m -348, 0
                        a 348,348 0 1, 0 696,0
                        a 348,348 0 1, 0 -696,0
                    " fill="none" stroke="#c9e3ff" stroke-width="12"></path>
    
      <g id="SvgjsG1234" class="circleFive">
          <circle id="SvgjsCircle1243" r="34.6" cx="215.5" cy="231.6" fill="#022549" cursor="pointer"></circle>
          <path id="SvgjsPath1244" d="M28,38.92A10.59,10.59,0,0,0,32.83,40c2,0,3.5-1.18,3.5-3s-1.64-3-4-3a10.83,10.83,0,0,0-4,.71l.5-12.46H41V27H33.73l-.12,3.29a6,6,0,0,1,1.33-.12c4.19,0,7.25,2.91,7.25,7.53S38.69,45,33.61,45A11.4,11.4,0,0,1,28,43.79Z" transform="matrix(1, 0, 0, 1, 181.136, 199.592)" cursor="pointer" fill="white"></path>
        
          <animateMotion dur="4s" 
            path="M 0, 0
                  a 348,348 0 1, 0 367.8, -590.8
                  a 348,348 0 1, 0 -367.8, 590.8"
            begin="click" fill="freeze" calcMode="linear" keyTimes="0;1" keyPoints="1;0" repeatCount="1"></animateMotion>
          
     </g>
          
    </svg>