SVG SMIL animations removed when used in a symbol? - html

I have an animated svg (like you can see here) which works when inlined... however when i convert the svg into a symbol so i can access it anywhere with xlink:href... browsers seem to strip out the animate tags from the svg.
SVG inlined: http://puu.sh/cLkTR/24db186e78.png
SVG symbol reference: http://puu.sh/cLkZ7/51051612d3.png
Couldn't find any documentation on if this is the expected behavior, so asking here to see if anyone knows. Thanks :)
EDIT
Here is a snippet of the svg "sprite sheet" as requested. http://pastebin.com/3tUYueCj
And this is how it is included in html:
<svg>
<use xlink:href="sprites.svg#icon-loading.spinning.bubbles"></use>
</svg>

It works fine in Chrome 38 if the symbols are defined in the same document as the use element (see snippet below).
Are you using an experimental version of Chrome? I am not seeing a "shadow root" definition for the use element in the Chrome DOM inspector -- that might be something new that is creating unexpected bugs. SVG use elements are not directly equivalent to web component shadow roots. You'll want to file a bug report if you haven't already.
svg.defs {
height: 0; width: 0; margin: 0; padding: 0; overflow: hidden;
}
svg.icon {
height: 2em;
width: 2em;
margin: 0.5em;
}
<svg class="defs" xmlns="http://www.w3.org/2000/svg">
<symbol viewBox="0 0 32 32" id="icon-loading.spinning.bubbles">
<title>loading.spinning.bubbles</title>
<circle cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(45 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.125s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(90 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.25s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(135 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.375s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(180 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.5s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(225 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.625s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(270 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.75s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(315 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.875s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
<circle transform="rotate(180 16 16)" cx="16" cy="3" r="0">
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.5s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
</circle>
</symbol>
</svg>
<svg class="icon"><use xlink:href="#icon-loading.spinning.bubbles"/></svg>

Related

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 SMIL animateTo works fine in Chrome but not in Firefox or Safari

I have created a SVG animation by using <animateTo> that works fine in Chrome, but not in Firefox or Safari.
It works when the keySplines and keyTimes attributes are removed, but I need those for a smooth animation.
This is my code:
<svg class="hiw-steps__morph" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" height="100%" width="100%" viewBox="0 0 500 500">
<path id="path0" d="M120.399523,21.2622729 C92.146201,2.04911041 37.1043026,11.4986169 13.0504556,35.6494234 C-11.0033913,59.8002298 -0.249326211,94.7145403 32.5542809,117.022042 C65.3578881,139.329544 101.512352,151.363715 132.710445,117.022042 C163.908538,82.680369 148.652846,40.4754353 120.399523,21.2622729 Z" fill="#FE8C3F"></path>
<animateTransform href="#path0" from="0 0" to="250 50" attributeType="XML" dur="1000ms" calcMode="spline" fill="freeze" keyTimes="0 ; 0.22 ; 0.33 ; 0.55 ; 0.66 ; 0.88 ; 1" keySplines="0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1" attributeName="transform" type="translate"></animateTransform>
</svg>
Link to codepen: https://codepen.io/SammySadati/pen/LoddPm
The problem is that you have 7 keytimes and only 2 values.
Also you need to put the animateTransform inside the path and I've changed dur from 5000ms to 5s
<svg class="hiw-steps__morph" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" height="100%" width="100%" viewBox="0 0 500 500">
<path id="path0" d="M120.399523,21.2622729 C92.146201,2.04911041 37.1043026,11.4986169 13.0504556,35.6494234 C-11.0033913,59.8002298 -0.249326211,94.7145403 32.5542809,117.022042 C65.3578881,139.329544 101.512352,151.363715 132.710445,117.022042 C163.908538,82.680369 148.652846,40.4754353 120.399523,21.2622729 Z" fill="#FE8C3F">
<animateTransform
attributeType="XML"
attributeName="transform"
type="translate"
from="0 0" to="250 50"
dur="5s"
fill="freeze"/></path>
</svg>
If you need 7 keytimes you will need to work with the attribute values instead of from and to
In the next example I'm using 4 values, 4 keyTimes and 3 keySplines:
<svg class="hiw-steps__morph" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" height="100%" width="100%" viewBox="0 0 500 500">
<path id="path0" d="M120.399523,21.2622729 C92.146201,2.04911041 37.1043026,11.4986169 13.0504556,35.6494234 C-11.0033913,59.8002298 -0.249326211,94.7145403 32.5542809,117.022042 C65.3578881,139.329544 101.512352,151.363715 132.710445,117.022042 C163.908538,82.680369 148.652846,40.4754353 120.399523,21.2622729 Z" fill="#FE8C3F">
<animateTransform
attributeType="XML" attributeName="transform" type="translate"
values= "0,0; 63,85; 170,-35; 0,0"
keyTimes= "0; 0.7; 0.9; 1"
dur="5s"
calcMode="spline"
keySplines= ".5 0 .5 1; 0 .75 .25 1; 1 0 .25 .25"
fill="freeze"
></animateTransform></path>
</svg>

animateTransform not working

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>

how to keep text orientation unchanged during rotation in SVG

I am using <g transform = "rotate(45, 10, 30)"> in svg to roate som circles and texts around a point at the same time, however, I want to keep orientation of each individual font the same (e.g., always facing one direction while the text is moved/rotated).
For example,how could I change the labels such as "A" in the right-side image to correct orientation after rotation?
How should I do that?
Thanks!
Pure SVG
Rotate the entire group of elements: triangle, spiral and colored circles with the letters
<g id = "common"`>
....
</g>
<animateTransform xlink:href="#common"
attributeName="transform"
type="rotate"
begin="svg1.click"
restart="whenNotActive"
repeatCount="indefinite"
dur="10s"
values="
0, 75.74, 74.91;
-360, 75.74, 74.91"
additive="sum" />
Inside is the second animation of the rotation of circles and letters.
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive"
repeatCount="indefinite" dur="10s"
values="
0, 56.13, 106.87;
360, 56.13, 106.87"
additive="sum" />
We find the coordinates of the center of rotation of the letters using the getBBox () JS method
<script>
//Find the center of rotation of the letter A
let bb = a1.getBBox();
console.log(bb.x+bb.width/2);
console.log(bb.y+bb.height/2);
</script>
The animation will start after clicking
text {
font-family:sans-serif;
font-size:14px;
font-weight:bold;
fill:#6E6E6E;
}
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="190px" height="190px" viewBox="0 0 150 150" version="1.1">
<defs>
</defs>
<g id="common">
<g transform="translate(-27.970238,-63.089294)">
<circle cx="102.9" cy="138.0" r="75" fill="#faa"/>
<path d="m163.7 175.2-121.5 0 60.8-105.2z" fill="#fea"/>
<!-- Spiral -->
<path d="m101.3 136.5c1.1 2-2.1 2.5-3.3 1.9-3.2-1.7-2.6-6.2-0.5-8.4 3.7-4.1 10.2-2.9 13.6 0.9 5 5.6 3.3 14.3-2.3 18.8-7.4 6-18.4 3.7-23.9-3.6-7-9.2-4.1-22.5 5-29.1 11-8 26.6-4.4 34.3 6.4 9 12.8 4.8 30.7-7.8 39.4-14.6 10-34.8 5.2-44.6-9.2-11.1-16.4-5.6-39 10.6-49.7 18.2-12.1 43.1-6 54.9 11.9 13.1 19.9 6.4 47.2-13.3 60.1" style="fill:none;stroke-width:1;stroke:#6E6E6E">
</path>
<g id="La">
<circle cx="55.9" cy="108.0" r="12.9" fill="#efa"/>
<text id="a1" x="51" y="112">
A
</text>
<!-- Animation of the rotation of the letter `A` -->
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 56.13, 106.87;360, 56.13, 106.87" additive="sum" />
</g>
<g>
<circle cx="153.7" cy="110.3" r="12.9" fill="#efa"/>
<text id="b1" xml:space="preserve" x="114" y="116" >
B
</text>
<!-- Animation of the rotation of the letter `B` -->
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 153.7, 110.3;360, 153.7, 110.3" additive="sum" />
</g>
<g>
<circle cx="105.2" cy="192.5" r="12.9" fill="#efa" />
<text id="c1" x="100" y="198" >
C
</text>
<!-- Animation of the rotation of the letter `C` -->
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 104.93, 193.46;360, 104.93, 193.46" additive="sum" />
</g>
</g>
</g>
<!-- Animating the rotation of the entire shape -->
<animateTransform xlink:href="#common" attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 75.74, 74.91;-360, 75.74, 74.91" additive="sum" />
</svg>
<script>
//Find the center of rotation of the letter A
let bb = a1.getBBox();
console.log(bb.x+bb.width/2);
console.log(bb.y+bb.height/2);
</script>
Example with adding animation of the ball movement in a spiral
text {
font-family:sans-serif;
font-size:14px;
font-weight:bold;
fill:#6E6E6E;
}
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="190px" height="190px" viewBox="0 0 150 150" version="1.1">
<defs>
</defs>
<g id="common">
<g transform="translate(-27.970238,-63.089294)">
<circle cx="102.9" cy="138.0" r="75" fill="#faa"/>
<path d="m163.7 175.2-121.5 0 60.8-105.2z" fill="#fea"/>
<path d="m163.7 175.2-121.5 0 60.8-105.2z" fill="#fea"/>
<!-- Spiral track (pink) -->
<path id="track" d="m101.3 136.5c1.1 2-2.1 2.5-3.3 1.9-3.2-1.7-2.6-6.2-0.5-8.4 3.7-4.1 10.2-2.9 13.6 0.9 5 5.6 3.3 14.3-2.3 18.8-7.4 6-18.4 3.7-23.9-3.6-7-9.2-4.1-22.5 5-29.1 11-8 26.6-4.4 34.3 6.4 9 12.8 4.8 30.7-7.8 39.4-14.6 10-34.8 5.2-44.6-9.2-11.1-16.4-5.6-39 10.6-49.7 18.2-12.1 43.1-6 54.9 11.9 13.1 19.9 6.4 47.2-13.3 60.1" style="fill:none;stroke-width:3;stroke:#FFAAAA"/>
<!-- Spiral -->
<path stroke-dasharray="0,432" d="m101.3 136.5c1.1 2-2.1 2.5-3.3 1.9-3.2-1.7-2.6-6.2-0.5-8.4 3.7-4.1 10.2-2.9 13.6 0.9 5 5.6 3.3 14.3-2.3 18.8-7.4 6-18.4 3.7-23.9-3.6-7-9.2-4.1-22.5 5-29.1 11-8 26.6-4.4 34.3 6.4 9 12.8 4.8 30.7-7.8 39.4-14.6 10-34.8 5.2-44.6-9.2-11.1-16.4-5.6-39 10.6-49.7 18.2-12.1 43.1-6 54.9 11.9 13.1 19.9 6.4 47.2-13.3 60.1" style="fill:none;stroke-width:2;stroke:#6E6E6E">
<!-- Spiral animation -->
<animate attributeName="stroke-dasharray" begin="svg1.click" repeatCount="indefinite" restart="whenNotActive" dur="10s" values="0,432;432,0;0,432" fill="freeze" />
</path>
<circle cx="0" cy="0" r="6" fill="#6E6E6E">
<!-- Ball movement in a spiral clockwise -->
<animateMotion id="forwards"
begin="svg1.click;back.end"
dur="5s" >
<mpath xlink:href="#track" />
</animateMotion>
<!-- Ball movement in a spiral counterclockwise -->
<animateMotion
id="back"
dur="5s"
begin="forwards.end"
repeatCount="1"
keyPoints="1;0"
keyTimes="0;1"
calcMode="linear"
rotate="auto"
fill="freeze" >
<mpath xlink:href="#track" />
</animateMotion>
</circle>
<g id="La">
<circle cx="55.9" cy="108.0" r="12.9" fill="#efa"/>
<text x="51" y="112"> A </text>
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 55.9, 108;360, 55.9, 108" additive="sum" />
</g>
<g>
<circle cx="153.7" cy="110.3" r="12.9" fill="#efa"/>
<text xml:space="preserve" x="114" y="116" >
B
</text>
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 153.7, 110.3;360, 153.7, 110.3" additive="sum" />
</g>
<g>
<circle cx="105.2" cy="192.5" r="12.9" fill="#efa" />
<text x="100" y="198" > C
</text>
<!-- Animation of the rotation of the letter `C` -->
<animateTransform attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 105.2, 192.5;360, 105.2, 192.5" additive="sum" />
</g>
</g>
</g>
<!-- Animating the rotation of the entire shape -->
<animateTransform xlink:href="#common" attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"
values="0, 75.38, 75;-360, 75.38, 75" additive="sum" />
</svg>
Instead of rotation of <g>roup and reverse rotation of the text within it, try this alternate grouping. Center the <g> around origin(0,0) with negative x= and y= values & use rotate(degree, 0, 0) on circle_group, then translate(x,y) on the main_group.
Edit: Here's an animated example, modified from this source. The trick is to move it around the origin with sin() and cos() trigonometric functions.
<!DOCTYPE html>
<html>
<head>
<title>JavaScript SVG Animation</title>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/> <!-- Remove this line in production. -->
</head>
<body>
<svg width="800px" height="800px" viewBox="0 0 800 800">
<g transform="translate(400, 400)"> <!-- Create a Cartesian coordinate system (with the y-axis flipped) for the animated square. That is, place the origin at the center of the 800 x 800 SVG viewport: -->
<!-- A 200 x 200 square with the upper left-hand corner at (-100, -100). This places the center of the square
at the origin (0, 0): -->
<rect id="mySquare" x="-100" y="-100" width="200" height="200" rx="5" ry="5"
style=" fill: yellow; stroke: yellow; stroke-width: 1; stroke-dasharray: 10, 5;" />
<!-- Represents the x-axis: -->
<line x1="-400" y1="0" x2="400" y2="0" style="stroke: blue;" />
<!-- Represents the y-axis (although up is negative and down is positive): -->
<line x1="0" y1="-400" x2="0" y2="400" style="stroke: blue;" />
<circle cx="0" cy="0" r="141" fill="none" stroke="yellow"/>
<g id="circle_a">
<circle cx="0" cy="0" r="10" fill="none" stroke="blue"/>
<text x="-5" y="5" width="20" height="20">A</text>
</g>
<g id="circle_b">
<circle cx="0" cy="0" r="10" fill="none" stroke="red"/>
<text x="-5" y="5" width="20" height="20">B</text>
</g>
</g>
</svg>
<script>
"use strict";
/* CONSTANTS */
var initialTheta = 0; // The initial rotation angle, in degrees.
var thetaDelta = 0.3; // The amount to rotate the square about every 16.7 milliseconds, in degrees.
var angularLimit = 180; // The maximum number of degrees to rotate the square.
var theSquare = document.getElementById("mySquare");
var circleA = document.getElementById("circle_a");
var circleB = document.getElementById("circle_b");
theSquare.currentTheta = initialTheta; // The initial rotation angle to use when the animation starts, stored in a custom property.
var requestAnimationFrameID = requestAnimationFrame(doAnim); // Start the loop.
function doAnim() {
if (theSquare.currentTheta > angularLimit) {
cancelAnimationFrame(requestAnimationFrameID); // The square has rotated enough, instruct the browser to stop calling the doAnim() function.
return; // No point in continuing, bail now.
}
theSquare.setAttribute("transform", "rotate(" + theSquare.currentTheta + ")"); // Rotate the square by a small amount.
circleA.setAttribute("transform", "translate(" +Math.cos((theSquare.currentTheta-45)*Math.PI/180)*141 + "," + Math.sin((theSquare.currentTheta-45)*Math.PI/180)*141+")"); // Move the circle A
circleB.setAttribute("transform", "translate(" +Math.cos((theSquare.currentTheta+45)*Math.PI/180)*141 + "," + Math.sin((theSquare.currentTheta+45)*Math.PI/180)*141+")"); // move the circle B
theSquare.currentTheta += thetaDelta; // Increase the angle that the square will be rotated to, by a small amount.
requestAnimationFrameID = requestAnimationFrame(doAnim); // Call the doAnim() function about 60 times per second (60 FPS), or about once every 16.7 milliseconds until cancelAnimationFrame() is called.
}
</script>

SVG animation translate

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>