15

How do I use animateTransform in an SVG to scale an object from the center point instead of the upper-left corner?

Example:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100px" height="100px">
    <circle style="fill:blue;" cx="50" cy="50" r="45">
        <animateTransform attributeName="transform"
             type="scale"
             from="0 0"
             to="1 1"
             begin="0s"
             dur="1s"
             repeatCount="indefinite"
        />
    </circle>
</svg>

(Codepen: http://codepen.io/anon/pen/wKwrPg?editors=100)

enter image description here

MattSidor
  • 2,599
  • 4
  • 21
  • 32

2 Answers2

17

Change your scaling transform to use additive="sum" and apply an additional transform that translates the circle to the center of the image. So instead of defining the shape at the center of the image, define its center to be 0 0 and then use the transform attribute to translate it to 50, 50 (the exact center of your particular image).

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100px" height="100px">
    <circle style="fill:blue;" cx="0" cy="0" r="45" transform="translate(50 50)">
        <animateTransform attributeName="transform"
             type="scale"
             additive="sum" 
             from="0 0"
             to="1 1"
             begin="0s"
             dur="1s"
             repeatCount="indefinite"
        />
    </circle>
</svg>

Here's another example using the defs and use tags to reuse the circle definition:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100px" height="100px">
    <defs>
        <circle id="def-circle" style="fill:blue;" cx="0" cy="0" r="45" />
    </defs>

    <use xlink:href="#def-circle" transform="translate(50 50)">
        <animateTransform attributeName="transform" 
        type="scale"
        additive="sum"    
        from="0 0"
        to="1 1"      
        beg="0s"
        dur="1s"
        repeatCount="indefinite" />
    </use>   
</svg>
trooper
  • 4,444
  • 5
  • 32
  • 32
  • How do you define it to be at the center if it's not a circle, for example a complex path? Just calculate the exact center point and then move there first then move to the real start location? – Justin Feb 26 '20 at 10:12
3

You could also have done that with the help of CSS styles and transform-origin property.
The benefit is that you do not have to calculate coordinates and translate your objects.

<svg version="1.1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <style>
    #logo { transform-origin: center; }
  </style>

  <g id="logo">
    <animateTransform attributeName="transform" begin="0s" type="scale" dur="2s" from="1" to=".5" repeatCount="indefinite"/>
    <circle r="8" cx="12" cy="12" />
  </g>
</svg>

#logo {
  transform-origin: center;
}
<svg version="1.1" viewBox="0 0 24 24" width="100%" height="100px" xmlns="http://www.w3.org/2000/svg">
  <g id="logo">
    <animateTransform attributeName="transform" begin="0s" type="scale" dur="2s" from="1" to=".5" repeatCount="indefinite"/>
    <circle r="8" cx="12" cy="12" />
  </g>  
</svg>

In your specific case, yet another way would be to animate the radius of the circle itself:

<circle r="0" cx="50" cy="50">
  <animate attributeName="r" from="0" to ="10" begin="1s" dur="300ms" fill="freeze" />
</circle>

Thanks to Robert Longson for this answer.

Mahozad
  • 18,032
  • 13
  • 118
  • 133