Animate a circle around the circumference of another big circle

Viewed 444

I want to move a small circle around the circumference of the big circle using only CSS.

@keyframes moveAround {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

#small {
  animation: moveAround 2s infinite linear;
}
<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
    <g id="circles">
      <circle id="big" cx="60" cy="50" r="30" fill="white" stroke="#2493AB" stroke-width="20" />
      <circle id="small" cx="60" cy="20" r="10" fill="#EF6868" />
    </g>
  </svg>

4 Answers

You must specify which coordinate the circle should rotate around. By default, this is coordinate 0,0, but you want it to orbit the center of the large circle.

In CSS, you do this with transform-origin:

#small {
    transform-origin: 60px 50px;
    animation: moveAround 2s infinite linear;
}
@keyframes moveAround {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}
<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
    <g id="circles">
        <circle id="big" cx="60" cy="50" r="30" fill="white" stroke="#2493AB" stroke-width="20" />
        <circle id="small" cx="60" cy="20" r="10" fill="#EF6868" />
    </g>
</svg>

A CSS only solution with no SVG

.box {
  width: 60px;
  height: 60px;
  border: 20px solid #2493AB;
  border-radius: 50%;
  position: relative;
}

.box::before {
  content: "";
  width: 20px;
  height: 20px;
  border-radius: 50%;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  background: #EF6868;
  animation: moveAround 3s linear infinite;
}

@keyframes moveAround {
  from {
    transform: rotate(0deg) translate(40px);
  }
  to {
    transform: rotate(360deg) translate(40px);
  }
}
<div class="box"></div>

Pure SMIL SVG solution

To rotate the ball, use animateTransform

<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
    <g id="circles">
      <circle id="big" cx="60" cy="50" r="30" fill="white" stroke="#2493AB" stroke-width="20" />
      <circle id="small" cx="60" cy="20" r="10" fill="#EF6868" >
       <animateTransform
         attributeName="transform"
         type="rotate"
         begin="0s"
         dur="3s"
         values="
           0 60 50;
           360 60 50"
          repeatCount="indefinite" /> 
      </circle>
    </g>
  </svg>

Ball rotation with pauses between full revolutions

<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
    <g id="circles">
      <circle id="big" cx="60" cy="50" r="30" fill="white" stroke="#2493AB" stroke-width="20" />
      <circle id="small" cx="60" cy="20" r="10" fill="#EF6868" >
       <animateTransform id="an"
         attributeName="transform"
         type="rotate"
         begin="0s;an.end+1s"
         dur="2s"
         values="
           0 60 50;
           360 60 50"
           /> 
      </circle>
    </g>
  </svg>

Back and forth rotation

<svg width="120" height="100" viewBox="0 0 120 100" fill="none" xmlns="http://www.w3.org/2000/svg">
    <g id="circles">
      <circle id="big" cx="60" cy="50" r="30" fill="white" stroke="#2493AB" stroke-width="20" />
      <circle id="small" cx="60" cy="20" r="10" fill="#EF6868" >
       <animateTransform
         attributeName="transform"
         type="rotate"
         begin="0s"
         dur="4s"
         values="
           0 60 50;
           360 60 50;
           360 60 50;
           0 60 50;
           0 60 50"
          repeatCount="indefinite" /> 
      </circle>
    </g>
  </svg>

Another idea with single div.

.circle {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  position: relative;
  background: radial-gradient(#EF6868 0 9.5px, transparent 10.5px) 50% 0% / 20px 20px no-repeat, 
              radial-gradient(transparent 29px, #2493AB 30px 50px) 0 0 / 100% 100% no-repeat;
  animation: animate 3s linear infinite;
}


@keyframes animate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
<div class="circle"></div>

Related