SVG animation translate - html

I try to make a next and previous button with SVG
There are square and triangle. When you see square, If you click next, It should change to triangle. And when you see triangle, If you click previous, It should change back to square.
If I click next then previous, It works perfectly. But when I try to click next again. It not works.
Here is my SVG code
<!DOCTYPE HTML>
<html>
<body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="300" height="300">
<text id="previous" x="50" y="250" font-family="Verdana" font-size="30" fill="blue" >
Prev
</text>
<text id="next" x="200" y="250" font-family="Verdana" font-size="30" fill="blue" >
Next
</text>
<g>
<path id="triangle" d="M450 0 L375 200 L525 200 Z"
stroke="#000000" stroke-width="3"
fill="white">
<animateColor attributeName="fill"
to="rgb(0,255,0)" begin="mouseover" dur="1s"
additive="sum" fill="freeze"/>
<animateColor attributeName="fill"
to="rgb(255,255,255)" begin="mouseout" dur="1s"
additive="sum" fill="freeze"/>
</path>
<path id="square" d="M75 0 L225 0 L225 200 L75 200 Z"
stroke="#000000" stroke-width="3"
fill="white">
<animateColor attributeName="fill"
to="rgb(255,0,0)" begin="mouseover" dur="1s"
additive="sum" fill="freeze"/>
<animateColor attributeName="fill"
to="rgb(255,255,255)" begin="mouseout" dur="1s"
additive="sum" fill="freeze"/>
</path>
<animateTransform attributeName="transform" attributeType="XML"
type="translate" by="-300,0" begin="next.click" dur="1s"
keyTimes="0; 1" calcMode="spline" keySplines=".5 0 .5 1"
additive="sum" accumulate="sum" fill="freeze"/>
<animateTransform attributeName="transform" attributeType="XML"
type="translate" by="300,0" begin="previous.click" dur="1s"
keyTimes="0; 1" calcMode="spline" keySplines=".5 0 .5 1"
additive="sum" accumulate="sum" fill="freeze"/>
</g>
</body>
</html>

This fixes it for me. Note that you should avoid animateColor and use animate instead as animateColor is deprecated in the SVG specification.
<!DOCTYPE HTML>
<html>
<body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="300" height="300">
<text id="previous" x="50" y="250" font-family="Verdana" font-size="30" fill="blue" >
Prev
</text>
<text id="next" x="200" y="250" font-family="Verdana" font-size="30" fill="blue" >
Next
</text>
<g>
<path id="triangle" d="M450 0 L375 200 L525 200 Z"
stroke="#000000" stroke-width="3"
fill="white">
<animate attributeName="fill"
to="rgb(0,255,0)" begin="mouseover" dur="1s"
additive="sum" fill="freeze"/>
<animate attributeName="fill"
to="rgb(255,255,255)" begin="mouseout" dur="1s"
additive="sum" fill="freeze"/>
</path>
<path id="square" d="M75 0 L225 0 L225 200 L75 200 Z"
stroke="#000000" stroke-width="3"
fill="white">
<animate attributeName="fill"
to="rgb(255,0,0)" begin="mouseover" dur="1s"
additive="sum" fill="freeze"/>
<animate attributeName="fill"
to="rgb(255,255,255)" begin="mouseout" dur="1s"
additive="sum" fill="freeze"/>
</path>
<animateTransform attributeName="transform" attributeType="XML"
type="translate" from="0,0" by="-300,0" begin="next.click" dur="1s"
keyTimes="0; 1" calcMode="spline" keySplines=".5 0 .5 1"
fill="freeze"/>
<animateTransform attributeName="transform" attributeType="XML"
type="translate" from="-300,0" by="300,0" begin="previous.click" dur="1s"
keyTimes="0; 1" calcMode="spline" keySplines=".5 0 .5 1"
fill="freeze"/>
</g>
</body>
</html>

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

Hide SVG element halfway animation

I have a repeating 20-second svg animation. Halfway (10 seconds) it should abruptly hide one path-element called leftside. When the animation finishes and repeats, it should show the element again. How can I achieve this?
Right now, I got the first loop working. But the reset when the animation repeats isn't working unfortunately.
This is what I have:
<svg class="svg-object" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1923 643" preserveAspectRatio="xMinYMin meet">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10"
d="M1438.8,348.8c6.2,189.4-75.3,34.5-157.8,28.3c-515.1,38.8-757.8,54.5-849.3,72.8
c-17.9,10.9-13.4,91.9-14.9,155.8"
/>
<g id="vehicle">
<path id="rightside" d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path id="leftside" d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/>
</g>
<animateMotion id="movement"
xlink:href="#vehicle"
dur="20s"
begin="0;movement.end+4s"
fill="freeze"
keyPoints="0;1;0"
keyTimes="0;0.5;1"
calcMode="spline"
keySplines= ".6 .01 .2 1; 0.6 .01 .2 1";
>
<mpath xlink:href="#motionPath" />
</animateMotion>
<animate xlink:href="#leftside" attributeName="opacity" from="1" to="0" dur="0.01s" begin="10s;movement.begin+10s;" repeatCount="indefinitive" fill="freeze" />
<animate xlink:href="#leftside" attributeName="opacity" from="0" to="1" dur="0.01s" begin="movement.begin" repeatCount="indefinitive" fill="freeze" />
</svg>
Mybe so?
<svg class="svg-object" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1923 643" preserveAspectRatio="xMinYMin meet">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10"
d="M1438.8,348.8c6.2,189.4-75.3,34.5-157.8,28.3c-515.1,38.8-757.8,54.5-849.3,72.8
c-17.9,10.9-13.4,91.9-14.9,155.8"
/>
<g id="vehicle" stroke-width="2" stroke="red">
<path id="rightside" d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path id="leftside" d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/>
</g>
<!-- Two dash move forward 10s -->
<animateMotion id="movement_forward"
xlink:href="#vehicle"
dur="10s"
begin="0;movement_back.end"
keyPoints="0;1"
keyTimes="0;1"
calcMode="linear"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
<!-- One dash goes back 10 seconds -->
<animateMotion id="movement_back"
xlink:href="#rightside"
dur="10s"
begin="movement_forward.end"
keyPoints="1;0"
keyTimes="0;1"
calcMode="linear"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
</svg>
begin="0;movement_back.end" - the restart of the first animation starts after the end of the second animation
begin="movement_forward.end - thus, two animations loop. When the first animation ends, the second animation begins
For uneven movement on different sections of the path, you need to change the attribute values:
keyPoints="0;0.2;0.4;0.8;1"
keyTimes="0;0.495;0.6;0.75;1"
<svg class="svg-object" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1923 643" preserveAspectRatio="xMinYMin meet">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10"
d="M1438.8,348.8c6.2,189.4-75.3,34.5-157.8,28.3c-515.1,38.8-757.8,54.5-849.3,72.8
c-17.9,10.9-13.4,91.9-14.9,155.8"
/>
<g id="vehicle" stroke-width="2" stroke="red">
<path id="rightside" d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path id="leftside" d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/>
</g>
<!-- Two dash move forward 10s -->
<animateMotion id="movement_forward"
xlink:href="#vehicle"
dur="10s"
begin="0;movement_back.end"
keyPoints="0;0.2;0.4;0.8;1"
keyTimes="0;0.495;0.6;0.75;1"
calcMode="linear"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
<!-- One dash goes back 10 seconds -->
<animateMotion id="movement_back"
xlink:href="#rightside"
dur="10s"
begin="movement_forward.end"
keyPoints="1;0.8;0.4;0.2;0"
keyTimes="0;0.495;0.6;0.75;1"
calcMode="linear"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
</svg>
This is hard to follow for me, but I got this solution:
<svg class="svg-object" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1923 643" preserveAspectRatio="xMinYMin meet">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10"
d="M1438.8,348.8c6.2,189.4-75.3,34.5-157.8,28.3c-515.1,38.8-757.8,54.5-849.3,72.8
c-17.9,10.9-13.4,91.9-14.9,155.8"
/>
<g id="vehicle">
<path id="rightside" d="M13,2c-0.6,0-1-0.4-1-1s0.4-1,1-1s8,0.4,8,1S13.6,2,13,2z"/>
<path id="leftside" d="M8,2C7.4,2,0,1.6,0,1s7.4-1,8-1s1,0.4,1,1S8.6,2,8,2z"/>
</g>
<animateMotion id="movement"
xlink:href="#vehicle"
dur="20s"
begin="0;movement.end+4s"
fill="freeze"
keyPoints="0;1;0"
keyTimes="0;0.5;1"
calcMode="spline"
keySplines= ".6 .01 .2 1; 0.6 .01 .2 1";
>
<mpath xlink:href="#motionPath" />
</animateMotion>
<animate xlink:href="#leftside" attributeName="opacity" from="1" to="0" dur="0.01s" begin="movement.begin+10s; 20s" fill="freeze" />
<animate xlink:href="#leftside" attributeName="opacity" from="0" to="1" dur="0.01s" begin="movement.begin" fill="freeze" />
</svg>
A couple of points:
If you want to repeat the animation, the keyword is indefinite, not indefinitive.
You apparently wanted to set the leftside animation to indefinite. This would apply to the opacity animation itself, with a 0.01s duration. This means that, after being triggered, the animation would be repeating itself every 0.01s in a blinking pattern.
I believe the issue here is related to the interplay between both leftside animations, and which one has the preference at each time. However, it looks like a complex issue, and I do not understand it fully (explained here).

Svg fill animation for the given path

I am trying to animate an arrow from left to right.The code of my arrow's path is given below:
<svg id="svg_circle" width="100%" height="100%" viewBox = '0 0 450 400'>
<g transform = "translate(0,0)">
<path class="path" stroke="#F0F0F0" fill="#fff" stroke-width="1" opacity="1" d="m34.97813,21.70979l-33.55223,0.47088l-0.0394,-13.57138l34.2665,-0.47295l-0.0208,-7.14282l14.50618,14.42226l-14.95643,15.04345l-0.20382,-8.74944z" id="svg_1">
<animate id="project_anim1" attributeName="fill" from="#fff" to="#4DAF4C" begin="1s" dur="1s" fill="freeze" repeatCount="1"></animate>
</path>
</g>
</svg>
The above is the svg path content of my arrow.
Kindly anyone help me how to fill the path from left to right. Waiting for quick response
You can do this by just animating the <stop>s in a <linear gradient>.
<svg id="svg_circle" width="100%" height="100%" viewBox = '0 0 450 400'>
<defs>
<linearGradient id="left-to-right">
<stop offset="0" stop-color="#4DAF4C">
<animate dur="2s" attributeName="offset" fill="freeze" from="0" to="1" />
</stop>
<stop offset="0" stop-color="#fff">
<animate dur="2s" attributeName="offset" fill="freeze" from="0" to="1" />
</stop>
</linearGradient>
</defs>
<path class="path" stroke="#F0F0F0" fill="url(#left-to-right)" stroke-width="1" opacity="1" d="m34.97813,21.70979l-33.55223,0.47088l-0.0394,-13.57138l34.2665,-0.47295l-0.0208,-7.14282l14.50618,14.42226l-14.95643,15.04345l-0.20382,-8.74944z" id="svg_1" />
</svg>
How this works is that we have a linear gradient representing an abrupt change from green to white. The <animation> elements move the position, of that abrupt change, from the left of the arrow (offset=0) to the right (offset="1").
Note that SVG <animate> elements will not work in IE. If you need to support IE, you will need to use the FakeSmile library or use a different method (such as a JS animation library).
Building upon andreas' answer. You can cover your arrow with a shape that is animated to uncover it.
<svg id="svg_circle" width="450" height="400" viewBox='0 0 450 400'>
<path class="path" stroke="#F0F0F0" fill="#fff"
stroke-width="1" opacity="1" id="svg_1"
d="m34.97813,21.70979l-33.55223,0.47088l-0.0394,
-13.57138l34.2665,-0.47295l-0.0208,-7.14282
l14.50618,14.42226l-14.95643,15.04345l-0.20382,
-8.74944z">
<animate id="project_anim1" attributeName="fill"
from="#fff" to="#4DAF4C" begin="0s" dur="3s"
fill="freeze" repeatCount="indefinite" />
</path>
<rect x="0" y="0" width="53" height="34" fill="#fff">
<animate attributeType="XML" attributeName="x"
from="0" to="53" begin="0s" dur="3s"
repeatCount="indefinite" />
<animate attributeType="XML" attributeName="width"
from="53" to="0" begin="0s" dur="3s"
repeatCount="indefinite" />
</rect>
</svg>
I don't think this is possible with the fill attribute. But instead, you can invert your SVG path to a rectangle with a triangle like hole. Now you just need a second element behind that path, where you can simply animate the scale in x-direction, to fill the hole from left to right.
Here is an image showing the technique:
An here is a working example:
<svg width="100%" height="100%" viewBox='0 0 450 400'>
<rect x="0" y="0" width="1" height="22" style="fill: black;" >
<animateTransform attributeName="transform" type="scale" from="1 1" to="50 1" begin="0s" dur="2s" repeatCount="indefinite" />
</rect>
<path fill="#ffffff" d="M0,0v29.8h86V0H0z M6.5,25V5.5L48.8,25H6.5z"/>
</svg>
Note: The answer was updated from triangle to arrow, I won't update my answer as the technique is the same for every shape.
<svg id="svg_circle" width="100%" height="100%" viewBox = '0 0 450 400'>
<defs>
<linearGradient id="left-to-right">
<stop offset="0" stop-color="#4DAF4C">
<animate dur="2s" attributeName="offset" fill="freeze" from="0" to="1" />
</stop>
<stop offset="0" stop-color="#fff">
<animate dur="2s" attributeName="offset" fill="freeze" from="0" to="1" />
</stop>
</linearGradient>
</defs>
<path class="path" stroke="#F0F0F0" fill="url(#left-to-right)" stroke-width="1" opacity="1" d="m34.97813,21.70979l-33.55223,0.47088l-0.0394,-13.57138l34.2665,-0.47295l-0.0208,-7.14282l14.50618,14.42226l-14.95643,15.04345l-0.20382,-8.74944z" id="svg_1" />
</svg>

SVG animation doesn't follow the defined path

I am working on a svg animation in which the animation has to trace the path which i defined previously,but the intial position of the animation when its starts seems to get displaced to another place but it still traces the same path but on different co-ordinates.
I want to the animation to follow along the path which is defined.
<svg width="500" height="500" viewBox="0 0 1000 1000">
<path id="motionPath" fill="none" stroke="#000000" stroke-miterlimit="10" d="M0,342.8c0,0,138.4-1.5,221.8-50.1c0,0,150.2-87.8,344.6-28.3c16.5,5.1,31.7,9.7,45.5,13.9"/>
<path id="motion" fill="none" stroke="#000000" stroke-miterlimit="10" class="st0" d="M0,379.8c0,0,154.4-114.9,223.4-71.6s381.4,29.7,388.6-24.3"/>
<g id="car" transform="translate(0, 0)">
<path id="note" d="M248.8,306.8c0,0-24-7-28.5,11c0,0-3,16,21,16.5c0,0,19.5,2.3,18.5-28.8s0-61.2,0-61.2s42,9,19,31.5
c0,0,17-1,13.5-23c0,0-7.5-20-43-22L248.8,306.8z"/>
<animate attributeType="CSS" attributeName="opacity" from="1" to="0" dur="5s" repeatCount="indefinite" />
</g>
<g id="car1" transform="translate(0, 0)">
<path id="note" d="M248.8,306.8c0,0-24-7-28.5,11c0,0-3,16,21,16.5c0,0,19.5,2.3,18.5-28.8s0-61.2,0-61.2s42,9,19,31.5
c0,0,17-1,13.5-23c0,0-7.5-20-43-22L248.8,306.8z"/>
<animate attributeType="CSS" attributeName="opacity" from="1" to="0" dur="5s" repeatCount="indefinite" />
</g>
<animateMotion
xlink:href="#car1"
dur="3s"
begin="click"
fill="freeze"
repeatCount="indefinite"
>
<mpath xlink:href="#motion" />
</animateMotion>
<animateMotion
xlink:href="#car"
dur="3s"
begin="click"
fill="freeze"
repeatCount="indefinite"
>
<mpath xlink:href="#motionPath" />
</animateMotion>
</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.