Related
I did following demo:
svg{
width: 200px;
height: 200px;
}
body{
position: fixed;
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
<path id="star" d="M100,10 L122.45,69.1 L185.6,72.19 L136.33,111.8 L152.9,172.81 L100,138.2 L47.1,172.81 L63.67,111.8 L14.4,72.19 L77.55,69.1Z" fill="gray" stroke="lightgreen" stroke-linejoin="round" stroke-linecap="round" stroke-width="15">
<animate xlink:href="#star" attributeName="d" attributeType="XML" begin="0s" dur="2s" repeatCount="1" values="M100,10 L122.45,69.1 L185.6,72.19 L136.33,111.8 L152.9,172.81 L100,138.2 L47.1,172.81 L63.67,111.8 L14.4,72.19 L77.55,69.1Z;M300 210 L322.45 269.1 L385.6 272.19 L336.33 311.8 L352.9 372.81 L300 338.2 L247.1 372.81 L263.67 311.8 L214.4 272.19 L277.55 269.1Z;M100,10 L122.45,69.1 L185.6,72.19 L136.33,111.8 L152.9,172.81 L100,138.2 L47.1,172.81 L63.67,111.8 L14.4,72.19 L77.55,69.1Z"></animate>
<animateTransform xlink:href="#star" attributeName="transform" attributeType="XML" type="rotate" from="0 100 100" to="360 100 100" dur="2s" begin="0s" repeatCount="None" fill="freeze"></animateTransform>
</path>
</svg>
I was expecting that the star to move along a straight line while rotating. however, adding the rotating animation changed the movement path.
I am looking for an svg animate tag solution, instead of a css one
Thanks very much
This is how I would do it: instead of animating the d attribute of the star I would translate the star to the new location with animate In order to make the 2 animations work together I'm using additive="sum" for the second animation.
svg{width:90vh}
<svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
<path id="star" d="M100,10 L122.45,69.1 L185.6,72.19 L136.33,111.8 L152.9,172.81 L100,138.2 L47.1,172.81 L63.67,111.8 L14.4,72.19 L77.55,69.1Z" fill="gray" stroke="lightgreen" stroke-linejoin="round" stroke-linecap="round" stroke-width="15">
<animateTransform attributeName="transform" attributeType="XML" type="translate" to="300 300" dur="2s" begin="0s" repeatCount="1" fill="freeze" ></animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0 99.6 91.4" to="360 99.6 91.4" dur="2s" begin="0s" repeatCount="1" fill="freeze" additive="sum"></animateTransform>
</path>
</svg>
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
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)
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>
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>