Как анимировать движение круга по окружности другого большого круга с помощью SVG

Я хочу перемещать маленький круг по окружности большого круга, используя CSS или SVG

@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>

Свободный перевод вопроса https://stackoverflow.com/q/66838390/7394871 от участника @Subato Patnaik.


Ответы (4 шт):

Автор решения: Alexandr_TT

Вы должны указать, вокруг какой координаты круг должен вращаться. По умолчанию это координата 0,0, но вы хотите, чтобы она вращалась вокруг центра большого круга.

В CSS вы делаете это с помощью 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>

Свободный перевод ответа от участника @Sphinxxx.

→ Ссылка
Автор решения: Alexandr_TT

SMIL SVG решение

Для вращения шарика используйте 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>

Вращение шарика с паузами в конечной точке

<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>

Вращение вперед-назад

<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>

Свободный перевод ответа от участника @Alexandr_TT.

→ Ссылка
Автор решения: Alexandr_TT

Решение только для CSS без 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>

Свободный перевод ответа от участника @Temani Afif.

→ Ссылка
Автор решения: Sevastopol'

Элементы изображаем с помощью градиентов radial-gradient. Анимацию вращения имитируем с помощью трансформации transform: rotate.

.box {
  width: 100px; height: 100px; animation: circle 3s linear infinite;
  background:
    radial-gradient(yellow, yellow 9px, transparent 10px),
    radial-gradient(circle at center, transparent, transparent 30px, red 31px, red 49px, transparent 50px, transparent 100%);
  background-position: 0 -40px, 0 0;
}

@keyframes circle {0% {transform: rotate(0deg);} 100% {transform: rotate(360deg);}}
<div class="box"></div>

Такую анимацию конечно можно выполнить и с помощью позиционирования фона background-position, но тогда получится добрая простыня стилей, потому что позиционирование будет смещаться на пиксель-в-пиксель, так как анимация вращения должна быть по кругу. Поэтому приведу самый простой пример анимации с помощью позиционирования фона. При том, что анимация передвижения элемента не по кругу, правило @keyframes уже включает в себя пять кадров.

.box {
  width: 100px; height: 100px; animation: circle 5s linear infinite;
  background:
    radial-gradient(yellow, yellow 9px, transparent 10px),
    linear-gradient( 45deg, transparent, transparent 50px, red 51px, red 69px, transparent 70px, transparent 100%),
    linear-gradient( 0deg, transparent, red 0px, red 19px, transparent 19px, transparent 100%);
  background-position: -40px -41px, 0 -16px, 0 0;
}

@keyframes circle {
  0% {background-position: -40px -41px, 0 -16px, 0 0;}
  25% {background-position: 41px 41px, 0 -16px, 0 0;}
  50% {background-position: -40px 41px, 0 -16px, 0 0;}
  75% {background-position: 40px 41px, 0 -16px, 0 0;}
  100% {background-position: -40px -41px, 0 -16px, 0 0;}
}
<div class="box"></div>

→ Ссылка