How to set an origin point for svg's animateTransform

Viewed 534

If you view this SVG, I'm animating the transform property, and it moves from the top left by default. How do I change it to animate from the center instead?

<svg width="400" height="400" viewBox="0 0 400 400">
  <rect width="400" height="400" fill="#495ade"/>
  <g>
  <circle cx="50" cy="50" r="50" fill="#49de7d"/>
  <animateTransform attributeName="transform"
                    type="scale"
                    values="1 1;.5 .5;1 1"
                    begin="0s"
                    dur="1.5s"
                    repeatCount="indefinite"
                    calcMode="spline"
                    keySplines="0.4 0 0.5 1; 0.5 0 0.5 1"
                />
  </g>
</svg>

What I tried already:

This answer says to just throw X & Y coords after each of the values listed. So I tried values="1 1 50 50;.5 .5 50 50;1 1 50 50" but that kills the animation.

You can also use from and to instead of values, and include an X & Y origin, but I need 3 animation states, not two.

2 Answers
  • It's easiest to have the circle at the origin, that way the scale works from its centre.

  • Then we need to translate the <g> element instead so the circle appears at the same place.

  • Finally we need to actually animate the circle and not the <g> element by wrapping the animateTransform by the <circle> element.

<svg width="400" height="400" viewBox="0 0 400 400">
  <rect width="400" height="400" fill="#495ade"/>
  <g transform="translate(50, 50)">
  <circle cx="0" cy="0" r="50" fill="#49de7d">
  <animateTransform attributeName="transform"
                    type="scale"
                    values="1 1;.5 .5;1 1"
                    begin="0s"
                    dur="1.5s"
                    repeatCount="indefinite"
                    calcMode="spline"
                    keySplines="0.4 0 0.5 1; 0.5 0 0.5 1"
                />
    </circle>
  </g>
</svg>

  • Alternatively we could transform the circle itself and then use additive="sum" to apply the transform animation on top.

<svg width="400" height="400" viewBox="0 0 400 400">
  <rect width="400" height="400" fill="#495ade"/>
  <g>
  <circle cx="0" cy="0" r="50" fill="#49de7d"  transform="translate(50, 50)">
  <animateTransform attributeName="transform"
                    type="scale"
                    values="1 1;.5 .5;1 1"
                    begin="0s"
                    dur="1.5s"
                    repeatCount="indefinite"
                    calcMode="spline"
                    keySplines="0.4 0 0.5 1; 0.5 0 0.5 1"
                    additive="sum"
                />
    </circle>
  </g>
</svg>

Instead of the animation animateTransform type =" scale ", you can use the animation of increasing the radius of the circle

In this case, it will not be necessary to define the transform-origin since the circle is in the center of the canvas.

<svg width="400" height="400" viewBox="0 0 400 400">
  <rect width="400" height="400" fill="#495ade"/>
  <g>
  <circle cx="200" cy="200" r="50" fill="#49de7d">
  <animate attributeName="r"
                    values="50;25;50"
                    begin="0s"
                    dur="1.5s"
                    repeatCount="indefinite"
                    calcMode="spline"
                    keySplines="0.4 0 0.5 1; 0.5 0 0.5 1"
                /> 
    </circle>           
  </g>
</svg>

Pause animation in intermediate states

<svg width="400" height="400" viewBox="0 0 400 400">
  <rect width="400" height="400" fill="#495ade"/>
  <g>
  <circle cx="200" cy="200" r="50" fill="#49de7d">
  <animate attributeName="r"
                    values="50;25;25;50;50"
                    begin="0s"
                    dur="1.5s"
                    repeatCount="indefinite"               
                /> 
    </circle>           
  </g>
</svg>

Update

Consider Implementing CSS Animations

#crc1 {
transform-origin:center;
transform-box:fill-box;
animation: scale 1.5s infinite;
}

@keyframes scale {
0%{transform:scale(1);}
50%{transform:scale(.5);}
100%{transform:scale(1);}
}
<svg width="400" height="400" viewBox="0 0 400 400">
  <rect width="400" height="400" fill="#495ade"/>
  <g>
  <circle id="crc1" cx="200" cy="200" r="50" fill="#49de7d"/>
   </g>
</svg>

Upd2

SMIL animation

On excellent advice from @Sphinxxx, add css rules to the group tag, thus keeping the animateTransform SVG

<svg width="400" height="400" viewBox="0 0 400 400">
  <rect width="400" height="400" fill="#495ade"/>
  <g style="transform-origin: center; transform-box: fill-box;">
  <circle  cx="200" cy="200" r="50" fill="#49de7d"/>
  <animateTransform attributeName="transform"
                    type="scale"
                    values="1 1;.5 .5;1 1"
                    begin="0s"
                    dur="1.5s"
                    repeatCount="indefinite"
                    calcMode="spline"
                    keySplines="0.4 0 0.5 1; 0.5 0 0.5 1"
                />
  </g>
</svg>

Related