2

I want to create svg animation of solar system. I've managed to code most things, but I am stuck on moon rotating over Earth. Any Ideas how to make it working?

<svg viewBox="0 0 500 500">
    <!-- sun -->
    <circle cx="250" cy="250" r="30" style="stroke: none; fill:
    #fffb00;"></circle>
    
    <!-- earth -->
    <circle cx="170" cy="170" r="12" style="stroke: none; fill:
    #040e9e;">
        <animateTransform attributeName="transform" type="rotate" from="0
        250 250" to="360 250 250" `scale(1 1)` begin="0s" dur="7s" repeatCount="indefinite" />
    </circle>
    
    <!-- moon -->
    <circle cx="157" cy="157" r="3" style="stroke: none; fill:
    #040e9e;">
        <animateTransform attributeName="transform" type="rotate" from="0
        170 170" to="360 250 250" begin="0s" dur="10s" repeatCount="indefinite" />
    </circle>
</svg>

https://jsfiddle.net/txuovbgr/

Alexandr_TT
  • 13,635
  • 3
  • 27
  • 54
dafie
  • 951
  • 7
  • 25
  • This may help: https://stackoverflow.com/questions/5451135/embed-svg-in-svg Looking at this answer it seems an image file linking to an additional SVG file that has your Moon around Earth rotation embedded into this file may work for you. – dale landry Jul 01 '21 at 06:20
  • @dafie scale (1 1) in `animateTransform` only works when `type ="scale"`, so `scale` is an wrong attribute – Alexandr_TT Jul 01 '21 at 11:17

2 Answers2

2

You put both the earth and the moon in a group and you animateTransform the group and the moon

<svg viewBox="0 0 500 500">
  <!-- sun -->
  <circle cx="250" cy="250" r="30" style="stroke: none; fill:
    #fffb00;"></circle>

 
  <g>
     <!-- earth -->
    <circle cx="170" cy="170" r="12" style="stroke: none; fill:
    #040e9e;">
    </circle>

    <!-- moon -->
    <circle cx="157" cy="157" r="3" style="stroke: none; fill:
    red">
      <animateTransform attributeName="transform" type="rotate" from="0 170 170" to="360 170 170" begin="0s" dur="10s" repeatCount="indefinite" />
    </circle>

    <animateTransform attributeName="transform" type="rotate" from="0 250 250" to="360 250 250" scale(1 1) begin="0s" dur="7s" repeatCount="indefinite" />
  </g>

</svg>
enxaneta
  • 31,608
  • 5
  • 29
  • 42
2

You need to combine the earth and the moon into one group and rotate this group around the sun.

Within this group, the moon will rotate in its directory

<g id="earth">
        <circle cx="170" cy="170" r="12" style="stroke: none; 
          fill: green;">
        </circle>

        <!-- moon -->
        <circle id="moon" cx="185" cy="185" r="3" style="stroke: none; 
           fill:red">   
        <!-- Within this group, the moon will rotate in its directory -->
            <animateTransform attributeName="transform" type="rotate" from="0
            170 170" to="360 170 170" begin="0s" dur="10s" repeatCount="indefinite" />
        </circle> 
         
   </g>   
        <!-- Group rotation -->
     <animateTransform  xlink:href="#earth" attributeName="transform" type="rotate" from="0
            250 250" to="360 250 250"  begin="0s" dur="7s" repeatCount="indefinite" />

<!doctype html>
<html class="no-js" lang="">

<head>
    <meta charset="utf-8">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            overflow: hidden;
            /* background: url('./bg.png'); */
        }

        svg {
            position: fixed;
            top: 0;
            left: 0;
            height: 100%;
            width: 100%;
        }
    </style>
</head>

<body>
    <svg viewBox="0 0 500 500">

        <!-- sun -->
        <circle cx="250" cy="250" r="30" style="stroke: none; fill:
        #fffb00;"></circle>

        <!-- mercury -->
        <circle cx="215" cy="215" r="8" style="stroke: none; fill:
        #502d05;">
            <animateTransform attributeName="transform" type="rotate" from="0
            250 250" to="360 250 250" begin="0s" dur="1.7s" repeatCount="indefinite" />
        </circle>

        <!-- venus -->
        <circle cx="195" cy="195" r="10" style="stroke: none; fill:
        #eb9b40;">
            <animateTransform attributeName="transform" type="rotate" from="0
            250 250" to="360 250 250" ) begin="0s" dur="4s" repeatCount="indefinite" />
        </circle>

        <!-- earth -->
    <g id="earth">
        <circle cx="170" cy="170" r="12" style="stroke: none; fill: skyblue;">
           
        </circle>

        <!-- moon -->
        <circle id="moon" cx="185" cy="185" r="5" style="stroke: none; fill:#FFD417">
            <animateTransform attributeName="transform" type="rotate" from="0
            170 170" to="360 170 170" begin="0s" dur="10s" repeatCount="indefinite" />
        </circle> 
         
   </g> 
     <animateTransform  xlink:href="#earth" attributeName="transform" type="rotate" from="0
            250 250" to="360 250 250"  begin="0s" dur="7s" repeatCount="indefinite" />
        <!-- mars -->
        <circle cx="145" cy="145" r="11" style="stroke: none; fill:
        #af0404;">
            <animateTransform attributeName="transform" type="rotate" from="0
            250 250" to="360 250 250" begin="0s" dur="12s" repeatCount="indefinite" />
        </circle>

        <!-- jupiter -->
        <circle cx="110" cy="110" r="16" style="stroke: none; fill:
         #291702;">
            <animateTransform attributeName="transform" type="rotate" from="0
             250 250" to="360 250 250" begin="0s" dur="70s" repeatCount="indefinite" />
        </circle>
    </svg>
</body>

</html>

As a bonus

This was my answer

The animation of the solar system will start after clicking the start button

var zodiac = new Audio();
zodiac.src = 'https://svg-art.ru/files/zodiac.mp3';

function play() {
  zodiac.play();
}
.solar-system{
  background-color:#002;
  width:100%;
  height:100%;
 
}
.sun{
  
  fill:url(#gradSun);
  filter:url(#dropShadow2);
  
 }
.mercury-orbit{
  stroke:  rgba(255,255,255,.4);
  stroke-width:1;
  fill:none;
  }
.mercury{
   fill:url(#gradMercury);
   filter:url(#dropShadow1);
 }
 .venus-orbit{
  stroke:rgba(255,255,255,.4);
  stroke-width:1;
  fill:none;
  }
.venus{
   fill:url(#gradVenus);
   filter:url(#dropShadow1);
   
 }
 
 .Earth-orbit{
  stroke:rgba(255,255,255,.4);
    stroke-width:1;
  fill:none;
  }
.Earth{
   filter:url(#dropShadow1);
   fill:url(#gradEarth);
 }
 .Mars-orbit{
  stroke:rgba(255,255,255,.4);
    stroke-width:1;
  fill:none;
  }
.Mars{
   filter:url(#dropShadow1);
   fill:url(#gradMars);
 } 
 
 .Jupiter-orbit{
  stroke:rgba(255,255,255,.4);
    stroke-width:1;
  fill:none;
  }
.Jupiter{
   filter:url(#dropShadow1);
   fill:url(#gradJupiter);
 }
<div class="solar-system">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
      viewBox="0 0 500 400" > 
  
  <defs>
    <filter id="dropShadow1" 
        x="-20%" y="-20%" 
        width="150%" height="150%"
    >
     <feGaussianBlur   stdDeviation="1" />
    </filter>
     <filter id="dropShadow2" 
        x="-20%" y="-20%" 
        width="150%" height="150%">
        <feGaussianBlur   stdDeviation="4" />
     </filter>
      <radialGradient id="gradSun">
        <stop offset="80%" stop-color="yellow">
         <animate attributeName="offset" values="80%;20%;80%" dur="12s" repeatCount="indefinite" />
         </stop>
        <stop offset="100%" stop-color="gold" >
        <animate attributeName="stop-color" values="gold;red;gold" dur="6s" repeatCount="indefinite" />
        </stop>
      </radialGradient>
        <linearGradient id="gradEarth">
            <stop offset="40%" stop-color="dodgerblue"></stop>
            <stop offset="100%" stop-color="yellowgreen" ></stop>
        </linearGradient>
    <linearGradient id="gradMercury"> 
        <stop offset="20%" stop-color="#824549"></stop>
        <stop offset="20%" stop-color="#956356"></stop>  
        <stop offset="80%" stop-color="#5F3631" ></stop>
        <stop offset="100%" stop-color="#807019" ></stop>
    </linearGradient>
      <linearGradient id="gradVenus">
        <stop offset="40%" stop-color="#805050"></stop>
        <stop offset="100%" stop-color="yellow" ></stop>
      </linearGradient>
      
        <linearGradient id="gradMars">
        <stop offset="40%" stop-color="crimson"></stop>
        <stop offset="100%" stop-color="yellow" ></stop>
    </linearGradient>  
        <linearGradient id="gradJupiter">
        <stop offset="10%" stop-color="#AE5D49"></stop>
        <stop offset="10%" stop-color="#783632" ></stop>
        <stop offset="20%" stop-color="#C58460" ></stop>
        <stop offset="20%" stop-color="#866D65" ></stop>
        <stop offset="30%" stop-color="#995645" ></stop>
        <stop offset="30%" stop-color="#C58460" ></stop>
        <stop offset="40%" stop-color="#AE5D49" ></stop>
        <stop offset="40%" stop-color="#C58460" ></stop>
        <stop offset="50%" stop-color="#AE5D49"></stop>
        <stop offset="50%" stop-color="#783632" ></stop>
        <stop offset="60%" stop-color="#C58460" ></stop>
        <stop offset="60%" stop-color="#866D65" ></stop> 
        <stop offset="70%" stop-color="#995645" ></stop>
        <stop offset="70%" stop-color="#C58460" ></stop>
        <stop offset="80%" stop-color="#AE5D49" ></stop>
        <stop offset="80%" stop-color="#943A31" ></stop>
        
    </linearGradient>  

      
  </defs>
 
 <g id="btn1" onclick='play()' >
     <circle  cx="30" cy="45" r="8" fill="url(#gradEarth)" filter="url(#dropShadow1)" /> 
     <text id="txt1" x="15" y="70" font-size="1rem" fill="gold" >Start</text>
 </g>
 <!-- mercury -->
  <g>
  <animateTransform 
      attributeName="transform" 
      type="rotate"
      begin="btn1.click"      
      values="0 250 175;360 250 175" 
      dur="8s"
      repeatCount="indefinite"
  />
 <circle class="mercury-orbit" cx="250" cy="175" r="40"   />
 <circle class="mercury" cx="210" cy="175" r="6"  />
</g> 
   <!-- venus -->
   <g>
  <animateTransform 
      attributeName="transform" 
      type="rotate"
      begin="btn1.click"
      values="0 250 175;360 250 175" 
      dur="10s"
      repeatCount="indefinite"
  />
 <circle class="venus-orbit" cx="250" cy="175" r="60"     />
 <circle class="venus" transform="rotate(-45 250 175)" cx="190" cy="175" r="10"   />
</g> 
 <!-- Earth -->
   <g>
  <animateTransform 
      attributeName="transform" 
      type="rotate"
      begin="btn1.click"      
      values="0 250 175;360 250 175" 
      dur="12s"
      repeatCount="indefinite"
  />
 <circle class="Earth-orbit" cx="250" cy="175" r="90"     />
 <circle class="Earth" cx="160" cy="175" r="10" transform="rotate(45 250 175)"  />
</g>
    <!-- Mars -->
  <g>
  <animateTransform 
      attributeName="transform" 
      type="rotate"
      begin="btn1.click"      
      values="0 250 175;360 250 175" 
      dur="14s"
      repeatCount="indefinite"
  />
 <circle class="Mars-orbit" cx="250" cy="175" r="120"     />
 <circle class="Mars" cx="130" cy="175" r="8" transform="rotate(90 250 175)"  />
</g>  
    <!-- Jupiter -->
    <g>
  <animateTransform 
      attributeName="transform" 
      type="rotate" 
      begin="btn1.click"
      values="0 250 175;360 250 175" 
      dur="16s"
      repeatCount="indefinite"
  />
 <circle class="Jupiter-orbit" cx="250" cy="175" r="180"     />
 <circle class="Jupiter " cx="70" cy="175" r="20" transform="rotate(180 250 175)"  />
</g>
  <circle class="sun" cx="250" cy="175" r="18"  >
     <animate attributeName="r" values="18;18;22;22;22;18" dur="12s" repeatCount="indefinite" />
  </circle>
    
</div> 

When the animation is running, the track of the Zodiac group sounds.

Alexandr_TT
  • 13,635
  • 3
  • 27
  • 54