moshyfawn
moshyfawn

Reputation: 690

Manipulate svg circle origin to create rotation animation around center

I have a loader (spinner) drawn on a page via two <circle />. Need to spin both paths in a different direction with origin centered, so, circles spin around the center of an SVG and don't translate, per say.

Trying to animate it transform: rotate(360deg). Paths go haywire and have origin somewhere else. Tried managing viewBox for intended results and didn't succeed.

import React, { PureComponent } from 'react';
import styled from 'styled-components';
import { prop } from 'styled-tools';

class Loader extends PureComponent {
  render() {
    return (
      <Spinner
        xmlns="http://www.w3.org/2000/svg"
        width="200"
        height="200"
        preserveAspectRatio="xMidYMid"
        viewBox="0 0 100 100"
      >
        <circle
          className='outer'
          cx="50"
          cy="50"
          r="40"
          fill="none"
          stroke="#374a67"
          stroke-dasharray="63 63"
          stroke-linecap="round"
          stroke-width="4"
        />
        <circle
          className='inner'
          cx="50"
          cy="50"
          r="35"
          fill="none"
          stroke="#d50000"
          stroke-dasharray="55 55"
          stroke-dashoffset="55"
          stroke-linecap="round"
          stroke-width="4"
        />
      </Spinner>
    )
  }
}

const Spinner = styled.svg`
  & .outer {
    animation: rotate 2s linear infinite;
  }

  & .inner {
    animation: reverseRotate 2s linear infinite;
  }

  @keyframes rotate {
    100% {
      transform: rotate(360deg);
    }
  }

  @keyframes reverseRotate {
    100% {
      transform: rotate(-360deg);
    }
  }
`;


export default Loader;

Don't know how to make an actual working snippet out of my piece of code, sry

Here's an example of my current animation:

Here's an example of my current animation

Upvotes: 4

Views: 1427

Answers (2)

enxaneta
enxaneta

Reputation: 33024

You need to set the transform-origin in the center of your svg. However you may do it differently. Instead of animating the transform you may animate the stroke-dashoffset like this:

.outer {
    stroke-dashoffset:0;
    animation: rotate 2s linear infinite;
  }

.inner {
    animation: reverseRotate 2s linear infinite;
  }

 @keyframes rotate {
    100% {
      stroke-dashoffset:126px;
    }
  }

  @keyframes reverseRotate {
    100% {
      stroke-dashoffset:-55px;
    }
  }

svg{border:1px solid}
<svg  xmlns="http://www.w3.org/2000/svg"
        width="200"
        height="200"
        preserveAspectRatio="xMidYMid"
        viewBox="0 0 100 100"
      >
        <circle
          class='outer'
          cx="50"
          cy="50"
          r="40"
          fill="none"
          stroke="#374a67"
          stroke-dasharray="63"
          stroke-linecap="round"
          stroke-width="4"
        />
        <circle
          class='inner'
          cx="50"
          cy="50"
          r="35"
          fill="none"
          stroke="#d50000"
          stroke-dasharray="55"
          stroke-dashoffset="55"
          stroke-linecap="round"
          stroke-width="4"
        />
      </svg>

Upvotes: 4

Badrush
Badrush

Reputation: 1287

Welcome to Stack.

You need to make a few small tweaks to get it working.

  • Just use one animation that goes from 0% to 100%.
  • Animate from 0deg to 360deg

    @keyframes rotate {
       0% {
         transform: rotate(0deg);
       }
       100% {
         transform: rotate(360deg);
       }
     }
    

For the reverse animation, you can reverse the direction using

animation-direction: alternate; in your CSS

Upvotes: 1

Related Questions