animateTransform not working - html

I am trying to make a SVG group follow a SVG path and transform animate the group. I am trying to make #moon transform with animateTransform but nothing seems to work.
Can anyone spot the problem?
<svg width="100%" height="100%" viewBox="0 0 570 594" preserveAspectRatio="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="padding: 0 10px 0 18px;fill-rule:evenodd;clip-rule:evenodd;stroke-miterlimit:10;">
<path id="orbit" d="M146.719,183.637l-18.408,-7.796l-13.233,-6.252l-12.327,-6.302l-18.44,-9.379l-12.42,-11.695l-16.36,-10.421l-15.546,-10.511l-12.326,-12.281l-14.415,-14.728l-8.426,-16.45l-4.168,-14.276l2.084,-14.272l6.297,-11.239l8.019,-10.103l12.013,-6.302l16.682,-8.426l16.356,-4.169l22.804,-4.217l27.474,-4.168l22.03,0l21.75,1.042l24.881,1.042l20.524,1.042l26.875,3.126l27.917,5.211l41.477,9.293l37.047,10.702l41.159,12.782l35.33,14.012l19.808,8.426l25.874,12.554l18.86,11.423l18.578,11.556l18.815,14.105l17.777,16.951l12.233,16.718l8.345,17.187l1.091,27.64l-7.434,8.207l-11.194,10.466l-15.595,10.559l-24.221,7.844l-22.609,5.211l-30.925,3.265l-43.658,0l-32.546,-2.085" style="fill:none;stroke-width:0px;stroke:#ff6060;"/>
<g id="moon" style="transform: translateY(-130px) translateX(-53px);">
<path d="M77.39,295.34c0,-10.683 -8.658,-19.343 -19.342,-19.343c-10.683,0 -19.344,8.66 -19.344,19.343c0,10.683 8.661,19.343 19.344,19.343c10.684,0 19.342,-8.66 19.342,-19.343" style="fill:#fff;fill-rule:nonzero;"/>
<path d="M61.54,304.476c0,-2.967 -2.404,-5.373 -5.371,-5.373c-2.969,0 -5.373,2.406 -5.373,5.373c0,2.967 2.404,5.373 5.373,5.373c2.967,0 5.371,-2.406 5.371,-5.373" style="fill:#878787;fill-opacity:0.199997;fill-rule:nonzero;"/>
<animateMotion dur="6s" repeatCount="indefinite">
<mpath xlink:href="#orbit" />
</animateMotion>
<animateTransform attributeName="transform"
attributeType="XML"
type="rotate"
from="0 60 70"
to="360 60 70"
dur="10s"
repeatCount="indefinite"/>
</g>
</svg>

You're mixing a CSS transform with the SMIL animation of a transform attribute. Although SVG 2 suggests they should be the same thing, SVG 1.1 has them as different things. Until the SVG 2 specification and UAs implementation of SVG 2 gets closer to completion it's best not to mix these things.
I've converted the g element's transform to an attribute transform and the animations certainly seem to do something for me now on Firefox.
<svg width="100%" height="100%" viewBox="0 0 570 594" preserveAspectRatio="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="padding: 0 10px 0 18px;fill-rule:evenodd;clip-rule:evenodd;stroke-miterlimit:10;">
<path id="orbit" d="M146.719,183.637l-18.408,-7.796l-13.233,-6.252l-12.327,-6.302l-18.44,-9.379l-12.42,-11.695l-16.36,-10.421l-15.546,-10.511l-12.326,-12.281l-14.415,-14.728l-8.426,-16.45l-4.168,-14.276l2.084,-14.272l6.297,-11.239l8.019,-10.103l12.013,-6.302l16.682,-8.426l16.356,-4.169l22.804,-4.217l27.474,-4.168l22.03,0l21.75,1.042l24.881,1.042l20.524,1.042l26.875,3.126l27.917,5.211l41.477,9.293l37.047,10.702l41.159,12.782l35.33,14.012l19.808,8.426l25.874,12.554l18.86,11.423l18.578,11.556l18.815,14.105l17.777,16.951l12.233,16.718l8.345,17.187l1.091,27.64l-7.434,8.207l-11.194,10.466l-15.595,10.559l-24.221,7.844l-22.609,5.211l-30.925,3.265l-43.658,0l-32.546,-2.085" style="fill:none;stroke-width:0px;stroke:#ff6060;"/>
<g id="moon" transform="translate(-53, -130)">
<path d="M77.39,295.34c0,-10.683 -8.658,-19.343 -19.342,-19.343c-10.683,0 -19.344,8.66 -19.344,19.343c0,10.683 8.661,19.343 19.344,19.343c10.684,0 19.342,-8.66 19.342,-19.343" style="fill:#fff;fill-rule:nonzero;"/>
<path d="M61.54,304.476c0,-2.967 -2.404,-5.373 -5.371,-5.373c-2.969,0 -5.373,2.406 -5.373,5.373c0,2.967 2.404,5.373 5.373,5.373c2.967,0 5.371,-2.406 5.371,-5.373" style="fill:#878787;fill-opacity:0.199997;fill-rule:nonzero;"/>
<animateMotion dur="6s" repeatCount="indefinite">
<mpath xlink:href="#orbit" />
</animateMotion>
<animateTransform attributeName="transform"
attributeType="XML"
type="rotate"
from="0 60 70"
to="360 60 70"
dur="10s"
repeatCount="indefinite"/>
</g>
</svg>

Easy !
AnimateTransform tag has to be within
AnimateMotion tag, completely enclosed, not following.

Precessing Orbit:
<?xml version="1.0"?>
<svg width="940" height="360" viewBox="0 0 350 350"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<!-- Here is a red circle which will be moved along the motion path. -->
<g>
<path d="M10,110 A120,120 -45 0,1 110 10 A120,120 -45 0,1 10,110"
stroke="lightgrey" stroke-width="2"
fill="none" id="theMotionPath"/
<circle cx="470" cy="180" r="160" fill="paleblue" />
<circle cx="10" cy="110" r="3" fill="lightgrey" />
<circle cx="110" cy="10" r="3" fill="lightgrey" />
<circle cx="" cy="" r="10" fill="red">
<!-- Define the motion path animation -->
<animateMotion dur="6s" repeatCount="indefinite">
<animateTransform attributeName="transform"
attributeType="XML"
type="rotate"
from="0 440 190"
to="360 440 190"
dur="6s"
repeatCount="indefinite"/>
<mpath xlink:href="#theMotionPath"/>
</animateMotion>
</circle>
<animateTransform attributeName="transform"
attributeType="XML"
type="rotate"
from="0 60 70"
to="360 60 70"
dur="10s"
repeatCount="indefinite"/>
</g>
</svg>
Copy, paste, edit to your liking.

<!DOCTYPE html>
<div width="100%">
<svg style="background:plum" width="240px" height="120px"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<polygon points="60,30 90,90 30,90">
<animateTransform attributeName="transform"
attributeType="XML"
type="rotate"
from="0 60 70"
to="360 60 70"
dur="10s"
repeatCount="indefinite"/>
</polygon>
</svg>
</div>

Related

How to make a pulse animation on a svg path?

I'm able to make the pulse animation on the heart but on the second icon it's sliding, I don't understand why.
<svg>
<g transform="translate(50, 50)">
<path transform="translate(-50, -50)" d="M82.6,50L82.6,50c-0.2-8.1-6.9-15.2-15.1-15.2c-4.8,0-9,2.4-11.8,6c-2.8-3.6-7-6-11.8-6c-8.3,0-15,7.2-15.1,15.2h0c0,0,0,0.1,0,0.1c0,0,0,0.1,0,0.1c0,0.2,0.1,0.4,0.1,0.6c0.7,20.5,26.6,29,26.6,29s26.3-8.4,27.1-28.9c0-0.2,0.1-0.4,0.1-0.6c0,0,0-0.1,0-0.1C82.6,50.1,82.6,50.1,82.6,50z"/>
<animateTransform attributeType="XML" attributeName="transform" type="scale" values="1;1.5;1" additive="sum" begin="0s" dur="2s" repeatCount="indefinite"/>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1042.816 1297.406">
<g transform="translate(50, 50)">
<path transform="translate(-50, -50)" d="M698.467,114.89a10.209,10.209,0,0,1-3.787-.817c-13.05-5.219-51.65-19.04-65.74-21.65s-23.48-4.96-19.83-14.09,7.57-24.78,7.57-24.78,5.57-30.79,7.61-34.44c1.618-2.894,3.594-3.82,7.465-3.82,1.01,0,2.149.062,3.445.17,6.26.52,26.61,3.65,25.3,8.87s-2.6,7.92,8.87,10.09,49.374,13.388,51.457,18.084c2.47,5.567-3.977,24.786-8.147,35.217-3.732,9.321-4.754,27.166-14.213,27.166M628.979,10.6c-6.16,0-8.353,2.8-10.209,12.954-2.76,15.01-13.91,53.56-14.82,56.671a3.161,3.161,0,0,1-.14.4c-4.27,10.521,1.78,12.86,22,16.231,20.35,3.389,57.3,17,63.09,18.889,3.735,1.222,8.923,4.074,13.182,4.074,2.924,0,5.41-1.343,6.688-5.484,3.13-10.17,12.78-39.649,16.95-52.17s-4.95-18.79-17.74-21.92c-11.46-2.8-29.64-7.5-39.67-11.45a4.522,4.522,0,0,1-2.87-4.26c.14-8.97-6.28-9.83-22.41-12.2-6.227-.916-10.719-1.734-14.051-1.734" fill="#4cb5e3"/>
<animateTransform attributeType="XML" attributeName="transform" type="scale" values="1;1.5;1" additive="sum" begin="0s" dur="2s" repeatCount="indefinite"/>
</g>
</svg>
You will need to use a different transform like so:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1042.816 1297.406">
<g transform="translate(664.6295, 65.2095)">
<path transform="translate(-664.6295, -65.2095)" d="M698.467,114.89a10.209,10.209,0,0,1-3.787-.817c-13.05-5.219-51.65-19.04-65.74-21.65s-23.48-4.96-19.83-14.09,7.57-24.78,7.57-24.78,5.57-30.79,7.61-34.44c1.618-2.894,3.594-3.82,7.465-3.82,1.01,0,2.149.062,3.445.17,6.26.52,26.61,3.65,25.3,8.87s-2.6,7.92,8.87,10.09,49.374,13.388,51.457,18.084c2.47,5.567-3.977,24.786-8.147,35.217-3.732,9.321-4.754,27.166-14.213,27.166M628.979,10.6c-6.16,0-8.353,2.8-10.209,12.954-2.76,15.01-13.91,53.56-14.82,56.671a3.161,3.161,0,0,1-.14.4c-4.27,10.521,1.78,12.86,22,16.231,20.35,3.389,57.3,17,63.09,18.889,3.735,1.222,8.923,4.074,13.182,4.074,2.924,0,5.41-1.343,6.688-5.484,3.13-10.17,12.78-39.649,16.95-52.17s-4.95-18.79-17.74-21.92c-11.46-2.8-29.64-7.5-39.67-11.45a4.522,4.522,0,0,1-2.87-4.26c.14-8.97-6.28-9.83-22.41-12.2-6.227-.916-10.719-1.734-14.051-1.734" fill="#4cb5e3"/>
<animateTransform attributeType="XML" attributeName="transform" type="scale" values="1;1.5;1" additive="sum" begin="0s" dur="2s" repeatCount="indefinite"/>
</g>
</svg>
In order to get the new transformation I'm using getBBox() for the path. This is returning in this case SVGRect {x: 602.5171508789062, y: 10.600000381469727, width: 124.22491455078125, height: 109.21900939941406}
In order to get the transformation for the path:
x = 602.5171508789062 + 124.22491455078125/2
y = 10.600000381469727 + 109.21900939941406/2

SVG image at page load animation does not start from initial position

I made this Avatar image with SVG and added animation to it, the circle clips the man path but at page load it shows the path then it jumps to animation. How do I keep it so that it would not show the path until animation begins
<svg xmlns="http://www.w3.org/2000/svg" version="1" viewBox="25 70 160 160">
<defs>
<clipPath id="a">
<circle cx="105" cy="149" r="69"></circle>
</clipPath>
</defs>
<circle cx="105" cy="149" r="69" fill="#999" stroke="#848080" stroke-linecap="square" stroke-linejoin="round" stroke-width="3"></circle>
<g clip-path="url(#a)">
<g>
<defs>
<clipPath id="b">
<ellipse cx="105" cy="149" rx="68" ry="68"></ellipse>
</clipPath>
</defs>
<path fill="#ccc" stroke="#e3e3e3" clip-path="url(#b)" stroke-linecap="square" stroke-linejoin="round" stroke-width="3" d="M137 137c0 18-14 32-31 32s-31-14-31-32 14-32 31-32 31 14 31 32zm-70 36c-13 0-17 12-17 24 0 13 4 21 17 21h76c13 0 17-9 17-21 0-13-4-24-17-24h-17a26 26 0 0 1-43 0z"></path>
<animateTransform attributeName="transform" type="translate" from="0 120" to="0 0" begin="0s" dur="1.5s"></animateTransform>
<animate attributeName="opacity" attributeType="XML" from="0" to="1" begin="0s" dur="1s"></animate>
</g>
</g>
</svg>
Set the opacity of the object to 0 at the start in markup and then move the animations so they are children of the element itself rather than animating the parent <g> element. That way the animation has sufficient specificity to override the element's properties.
<svg xmlns="http://www.w3.org/2000/svg" version="1" viewBox="25 70 160 160">
<defs>
<clipPath id="a">
<circle cx="105" cy="149" r="69"></circle>
</clipPath>
</defs>
<circle cx="105" cy="149" r="69" fill="#999" stroke="#848080" stroke-linecap="square" stroke-linejoin="round" stroke-width="3"></circle>
<g clip-path="url(#a)">
<g>
<defs>
<clipPath id="b">
<ellipse cx="105" cy="149" rx="68" ry="68"></ellipse>
</clipPath>
</defs>
<path fill="#ccc" stroke="#e3e3e3" clip-path="url(#b)" stroke-linecap="square" stroke-linejoin="round" stroke-width="3" d="M137 137c0 18-14 32-31 32s-31-14-31-32 14-32 31-32 31 14 31 32zm-70 36c-13 0-17 12-17 24 0 13 4 21 17 21h76c13 0 17-9 17-21 0-13-4-24-17-24h-17a26 26 0 0 1-43 0z" opacity="0">
<animateTransform attributeName="transform" type="translate" from="0 120" to="0 0" begin="0s" dur="1.5s"></animateTransform>
<animate attributeName="opacity" from="0" to="1" begin="0s" dur="1s" fill="freeze"></animate>
</path>
</g>
</g>
</svg>

How do I make an ellipse rotate on its axis with svg?

I'm learning about how to animate with svg in HTML, and I need to rotate an ellips on its axis, so how I do it?
The only thing that I could do was to rotate the ellipse around the point x="0" y="0".
<ellipse cx="500" cy="300" rx="80" ry="160" transform="rotate(<angle> 0 0)">
<animateTransform
attributeName="transform"
from="0"
to="360"
dur="10s"
repeatCount="1"/>
Try this:
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" preserveAspectRatio="xMidYMid meet" viewBox="0 0 480 480">
<ellipse cx="240" cy="240" rx="80" ry="160">
<animateTransform attributeName="transform"
attributeType="XML"
type="rotate"
from="0 240 240"
to="360 240 240"
dur="10s"
repeatCount="indefinite"/>
</svg>
Basically the SMIL animation should point at the shape's center. In case of my Ellipse here it is 240,240 (cx, cy)

How to bring an image inside SVG?

I've come up with this SVG image.
<svg width="250px" height="250px" viewBox="0 0 250 250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<def>
</def>
<g id="i-define-a-black-ring-yellow" fill="#img10" transform="translate(20.000000, 20.000000)">
<g id="Group">
<circle id="Oval" stroke="#ff0000" stroke-width="2" cx="100" cy="100" r="100">
</circle>
<circle id="Oval" fill="#228B22" fill-rule="nonzero" cx="171" cy="31" r="16">
</circle>
<animateTransform attributeName="transform" type="rotate" from="0 100 100" to="360 100 100" begin="0s" dur="10s" repeatDur="indefinite"/>
</g>
</g>
</svg>
Fiddle here: http://jsfiddle.net/9zkfodwp/1377/
Now, I wanted an image inside the circle. So, I tried to use a clip-path1 and the code is below: But, that image doesn't appear here.
<svg width="250px" height="250px" viewBox="0 0 250 250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<def>
<clipPath id="myCircle">
<circle id="Oval" fill="#228B22" fill-rule="nonzero" cx="171" cy="31" r="16">
</circle>
</clipPath>
</def>
<g id="i-define-a-black-ring-yellow" fill="#img10" transform="translate(20.000000, 20.000000)">
<g id="Group">
<circle id="Oval" stroke="#ff0000" stroke-width="2" cx="100" cy="100" r="100">
</circle>
<image width="50" height="35" xlink:href="https://www.tutorialspoint.com/videotutorials/images/coding_ground_home.jpg" clip-path="url(#myCircle)" />
<animateTransform attributeName="transform" type="rotate" from="0 100 100" to="360 100 100" begin="0s" dur="10s" repeatDur="indefinite"/>
</g>
</g>
</svg>
Fiddle here: http://jsfiddle.net/9zkfodwp/1380/
My questions are:
Chrome doesn't display the image as in the above fiddle though.
The one in the fiddle - doesn't actually fit in to a circle. The image is in a square shape.
(The book image is in rectangle shape - shouldn't be it inside the circle ? As we are filling the circle with the image ?
Any ideas on what should be done on this regard will be appreciated.
There are a couple of things wrong with your fiddle:
It is <defs>, not <def>. That whole section was being ignored.
Your image and the clip path circle were in different places. They didn't overlap with one another. I've updated the <image> to be centred over the clip path circle.
<svg width="250px" height="250px" viewBox="0 0 250 250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="myCircle">
<circle id="Oval" cx="171" cy="31" r="16"/>
</clipPath>
</defs>
<g id="i-define-a-black-ring-yellow" fill="#img10" transform="translate(20.000000, 20.000000)">
<g id="Group">
<circle id="Oval" stroke="#ff0000" stroke-width="2" cx="100" cy="100" r="100"/>
<image x="146" y="14" width="50" height="35"
xlink:href="https://www.tutorialspoint.com/videotutorials/images/coding_ground_home.jpg"
clip-path="url(#myCircle)" />
<animateTransform attributeName="transform" type="rotate" from="0 100 100" to="360 100 100" begin="0s" dur="10s" repeatDur="indefinite"/>
</g>
</g>
</svg>
Is this what you're tying to do.
you need to flip the image on the x-y axis, you can do that by adding scale it and add transformation.
check this code:
<svg width="350px" height="350px" viewBox="0 0 350 350" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<def>
<clipPath id="myCircle">
<circle id="Oval" fill="#228B22" fill-rule="nonzero" cx="171" cy="31" r="16">
</circle>
</clipPath>
</def>
<g id="i-define-a-black-ring-yellow" fill="#img10" transform="translate(20.000000, 20.000000)">
<g id="Group" >
<circle id="Oval" stroke="#ff0000" stroke-width="2" cx="100" cy="100" r="100">
</circle>
<image width="50" height="35" xlink:href="https://www.tutorialspoint.com/videotutorials/images/coding_ground_home.jpg" clip-path="url(#myCircle)" transform="scale (-1, 1) translate(-60, 45)" />
<animateTransform attributeName="transform" type="rotate" from="0 100 100" to="360 100 100" begin="0s" dur="10s" repeatDur="indefinite"/>
</g>
</g>
</svg>

CSS transform-origin not working on SVG in Chrome

I'm trying to animate scale transformation around the object's center using SMIL, it works in Firefox 38, but not in Chrome 43, in Chrome the CSS transform-origin property seems ignored for some reason
Original
document.querySelector("#trigger").addEventListener("click", function(e){
if (e.ctrlKey)
document.querySelector("#triggerScaleOut").beginElement();
else
document.querySelector("#triggerScaleIn").beginElement();
}, false);
<svg version="1.1" width="512" height="512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="triggerContainer" transform="scale(1)" style="transform-origin: 150px 150px 0;">
<circle id="trigger" cx="150" cy="150" r="25" />
<animateTransform id="triggerScaleIn" begin="indefinite" values="1; 2" dur="0.5s"
type="scale"
attributeName="transform"
fill="freeze"/>
<animateTransform id="triggerScaleOut" begin="indefinite" values="2; 1" dur="0.5s"
type="scale"
attributeName="transform"
fill="freeze"/>
</g>
</svg>
I need this method to work in Chrome since its the cleanest/easiest.
I have tried other things that work like this:
Trial#1
document.querySelector("#trigger").addEventListener("click", function(e){
if ( e.ctrlKey )
document.querySelector("#triggerScaleOut").beginElement();
else
document.querySelector("#triggerScaleIn").beginElement();
}, false);
<svg version="1.1" width="512" height="512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="triggerContainerFix" transform="translate(150,150)">
<g id="triggerContainer" transform="scale(1)">
<circle id="trigger" cx="150" cy="150" r="25" transform="translate(-150,-150)"/>
<animateTransform id="triggerScaleIn" begin="indefinite" values="1; 2" dur="0.5s"
type="scale"
attributeName="transform"
fill="freeze"/>
<animateTransform id="triggerScaleOut" begin="indefinite" values="2; 1" dur="0.5s"
type="scale"
attributeName="transform"
fill="freeze"/>
</g>
</g>
</svg>
But it's a bit hacky, and i don't prefer it.
I also tried additive animations, but it is problematic (probably my fault)
Trial#2
document.querySelector("#trigger").addEventListener("click", function(e){
if (e.ctrlKey){
document.querySelector("#triggerScaleOut").beginElement();
document.querySelector("#triggerTranslateOut").beginElement();
}
else{
document.querySelector("#triggerScaleIn").beginElement();
document.querySelector("#triggerTranslateIn").beginElement();
}
}, false);
<svg version="1.1" width="512" height="512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="triggerContainer" transform="scale(1)">
<circle id="trigger" class="button" cx="150" cy="150" r="25" />
<animateTransform id="triggerTranslateIn" begin="indefinite" values="0,0; -150,-150" dur="0.5s"
type="translate"
attributeName="transform"
fill="freeze"
additive="sum"/>
<animateTransform id="triggerScaleIn" begin="indefinite" values="1; 2" dur="0.5s"
type="scale"
attributeName="transform"
fill="freeze"
additive="sum"/>
<animateTransform id="triggerTranslateOut" begin="indefinite" values="-150,-150; 0,0" dur="0.5s"
type="translate"
attributeName="transform"
fill="freeze"
additive="sum"/>
<animateTransform id="triggerScaleOut" begin="indefinite" values="2; 1" dur="0.5s"
type="scale"
attributeName="transform"
fill="freeze"
additive="sum"/>
</g>
</svg>
Any ideas? Thanks.
As you have discovered transform-origin has only recently become supported in browsers. So you probably shouldn't try to rely on it just yet.
Both of your "Trial" approaches are commonly used. IMO, the simplest approach is your "Trial #1" version. It's what I most commonly use. The idea is to apply the animation in a coordinate space where the element being scaled sits at the origin.
Here's a slightly simplified version of your sample.
document.querySelector("#trigger").addEventListener("click", function(e){
if ( e.ctrlKey )
document.querySelector("#triggerScaleOut").beginElement();
else
document.querySelector("#triggerScaleIn").beginElement();
}, false);
<svg version="1.1" width="512" height="512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="triggerContainer" transform="translate(150,150)">
<circle id="trigger" cx="0" cy="0" r="25">
<animateTransform id="triggerScaleIn" begin="indefinite" values="1; 2" dur="0.5s"
type="scale"
attributeName="transform"
fill="freeze"/>
<animateTransform id="triggerScaleOut" begin="indefinite" values="2; 1" dur="0.5s"
type="scale"
attributeName="transform"
fill="freeze"/>
</circle>
</g>
</svg>
I don't consider it hacky at all.