1

I found this code snippet online and I'm trying to reverse it so that the circle will go from fully white at 0% to 100% gradient circle and then stop the animation. However I can't seem to figure out the reversing part. I've tried fiddling with the values but can't seem to get the desired effect. Also would be good to get rid of the small outline that persists once the gradient part is not showing. cheers

#circle-loader-wrap {
  overflow: hidden;
  position: relative;
  margin-top: -10px;
  width: 200px;
  height: 200px;

  background: linear-gradient(90deg, #fdbd39,#ee6723,#E06387);
  border-radius: 200px;

  -ms-transform: rotate(180deg);
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  transform: rotate(180deg);
}

#circle-loader-wrap:after {
  content: '';
  position: absolute;
  left: 15px;
  top: 15px;
  width: 170px;
  height: 170px;
  border-radius: 50%;
  background-color: white;

}

#circle-loader-wrap div {
  overflow: hidden;
  position: absolute;
  width: 50%;
  height: 100%;
}

#circle-loader-wrap .loader {
  position: absolute;
  left: 100%;
  top: 0;
  width: 100%;
  height: 100%;
  border-radius: 1000px;
  background-color: white;
}

#circle-loader-wrap .left-wrap {
  left: 0;
}

#circle-loader-wrap .left-wrap .loader {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  transform-origin: 0 50% 0;
  -webkit-transform-origin: 0 50% 0;
  animation: loading-left 10s infinite linear;
  -webkit-animation: loading-left 10s infinite linear;
}

#circle-loader-wrap .right-wrap {
  left: 50%;
}

#circle-loader-wrap .right-wrap .loader {
  left: -100%;
  border-bottom-right-radius: 0;
  border-top-right-radius: 0;
  transform-origin: 100% 50% 0;
  -webkit-transform-origin: 100% 50% 0;
  animation: loading-right 10s infinite linear;
  -webkit-animation: loading-right 10s infinite linear;
}

@keyframes loading-left {
  0% {
    -webkit-transform: rotate(0deg);
  }
  50% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(180deg);
  }
}

@-webkit-keyframes loading-left {
  0% {
    -webkit-transform: rotate(0deg);
  }
  50% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(180deg);
  }
}

@keyframes loading-right {
  0% {
    transform: rotate(0deg);
  }
  50% {
    transform: rotate(180deg);
  }
    100% {
    -webkit-transform: rotate(180deg);
  }

}

@-webkit-keyframes loading-right {
  0% {
    -webkit-transform: rotate(0deg);
  }
  50% {
    -webkit-transform: rotate(180deg);
  }
  100% {
    -webkit-transform: rotate(180deg);
  }

}
        <div class="container mt-5">
            <div class="row">
              <div class="col-3">
                <div id="circle-loader-wrap">
                  <div class="left-wrap">
                    <div class="loader"></div>
                  </div>
                  <div class="right-wrap">
                    <div class="loader"></div>
                  </div>
                </div>
              </div>
            </div>
          </div>
Tim Foles
  • 11
  • 1

3 Answers3

2

@keyframes of CSS is the tricky part of this loading animation.

You can use dev tools to inspect these two elements, .left-wrap>.loader and .right-wrap>.loader. Once the .loader element overlaps with its container (.left-wrap or .left-wrap), it hides the gradient circle away.

The key point of this animation is the keyframe and rotation degree of these two loader element.

Take the left half circle and the following code for example, in this case, the visibility of the left half circle is controlled by .right-wrap and .right-wrap>.loader. When the rotation of .right-wrap>.loader is 180 degree, it does not overlap with its container and the whole left half is visible. loading animate description

While we reduce the rotation, the overlapped part of .right-wrap>.loader and its container increases which hides some of the circle away. loading animate description

Besides, to control the timing of rotation (which part of the circle, left or right, performs the rotation first), the key frame is divided into 2 parts, 0%-50% (the first part) and 50%-100% (the second part).

If we set the rotation the same in 0% and 50% keyframes, the element does not rotate in the first part of the animation. From that concept you can also tell that if 50% and 100% remain the same rotation, the second part of the animation has no rotation presented.

To control clockwise or counterclockwise, it's important to know that which degree the rotation starts and which degree the rotation ends. For clockwise animation, the rotation should start from 180 degree and ends with 360 degree while for counterclockwise it start from 180 degree and ends with 0 degree.

#circle-loader-wrap {
  overflow: hidden;
  position: relative;
  margin-top: -10px;
  width: 200px;
  height: 200px;

  background: linear-gradient(90deg, #fdbd39,#ee6723,#E06387);
  border-radius: 200px;

  -ms-transform: rotate(180deg);
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  transform: rotate(180deg);
}

#circle-loader-wrap:after {
  content: '';
  position: absolute;
  left: 15px;
  top: 15px;
  width: 170px;
  height: 170px;
  border-radius: 50%;
  background-color: white;

}

#circle-loader-wrap div {
  overflow: hidden;
  position: absolute;
  width: 50%;
  height: 100%;
}

#circle-loader-wrap .loader {
  position: absolute;
  left: 100%;
  top: 0;
  width: 100%;
  height: 100%;
  border-radius: 1000px;
  background-color: white;
}

#circle-loader-wrap .left-wrap {
  left: 0;
}

#circle-loader-wrap .left-wrap .loader {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  transform-origin: 0 50% 0;
  -webkit-transform-origin: 0 50% 0;
  animation: loading-left 10s infinite linear;
  -webkit-animation: loading-left 10s infinite linear;
}

#circle-loader-wrap .right-wrap {
  left: 50%;
}

#circle-loader-wrap .right-wrap .loader {
  left: -100%;
  border-bottom-right-radius: 0;
  border-top-right-radius: 0;
  transform-origin: 100% 50% 0;
  -webkit-transform-origin: 100% 50% 0;
  animation: loading-right 10s infinite linear;
  -webkit-animation: loading-right 10s infinite linear;
}

@keyframes loading-left {
  0% {
    -webkit-transform: rotate(180deg);
  }
  50% {
    -webkit-transform: rotate(180deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
  }
}

@-webkit-keyframes loading-left {
  0% {
    -webkit-transform: rotate(180deg);
  }
  50% {
    -webkit-transform: rotate(180deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
  }
}

@keyframes loading-right {
  0% {
    transform: rotate(180deg);
  }
  50% {
    transform: rotate(360deg);
  }
    100% {
    -webkit-transform: rotate(360deg);
  }

}

@-webkit-keyframes loading-right {
  0% {
    -webkit-transform: rotate(180deg);
  }
  50% {
    -webkit-transform: rotate(360deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
  }

}
        <div class="container mt-5">
            <div class="row">
              <div class="col-3">
                <div id="circle-loader-wrap">
                  <div class="left-wrap">
                    <div class="loader"></div>
                  </div>
                  <div class="right-wrap">
                    <div class="loader"></div>
                  </div>
                </div>
              </div>
            </div>
          </div>
momocow
  • 833
  • 1
  • 11
  • 17
0

One method is to adjust the parameters for transform: rotate() in the animations:

#circle-loader-wrap {
  overflow: hidden;
  position: relative;
  margin-top: -10px;
  width: 200px;
  height: 200px;
  background: linear-gradient(90deg, #fdbd39, #ee6723, #E06387);
  border-radius: 200px;
  -ms-transform: rotate(180deg);
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  transform: rotate(180deg);
}

#circle-loader-wrap:after {
  content: '';
  position: absolute;
  left: 15px;
  top: 15px;
  width: 170px;
  height: 170px;
  border-radius: 50%;
  background-color: white;
}

#circle-loader-wrap div {
  overflow: hidden;
  position: absolute;
  width: 50%;
  height: 100%;
}

#circle-loader-wrap .loader {
  position: absolute;
  left: 100%;
  top: 0;
  width: 100%;
  height: 100%;
  border-radius: 1000px;
  background-color: white;
}

#circle-loader-wrap .left-wrap {
  left: 0;
}

#circle-loader-wrap .left-wrap .loader {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  transform-origin: 0 50% 0;
  -webkit-transform-origin: 0 50% 0;
  animation: loading-left 10s infinite linear;
  -webkit-animation: loading-left 10s infinite linear;
}

#circle-loader-wrap .right-wrap {
  left: 50%;
}

#circle-loader-wrap .right-wrap .loader {
  left: -100%;
  border-bottom-right-radius: 0;
  border-top-right-radius: 0;
  transform-origin: 100% 50% 0;
  -webkit-transform-origin: 100% 50% 0;
  animation: loading-right 10s infinite linear;
  -webkit-animation: loading-right 10s infinite linear;
}

@keyframes loading-left {
  0% {
    -webkit-transform: rotate(-180deg);
  }
  50% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(0deg);
  }
}

@-webkit-keyframes loading-left {
  0% {
    -webkit-transform: rotate(-180deg);
  }
  50% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(0deg);
  }
}

@keyframes loading-right {
  0% {
    transform: rotate(-180deg);
  }
  50% {
    transform: rotate(-180deg);
  }
  100% {
    -webkit-transform: rotate(0deg);
  }
}

@-webkit-keyframes loading-right {
  0% {
    -webkit-transform: rotate(-180deg);
  }
  50% {
    -webkit-transform: rotate(-180deg);
  }
  100% {
    -webkit-transform: rotate(0deg);
  }
}
<div class="container mt-5">
  <div class="row">
    <div class="col-3">
      <div id="circle-loader-wrap">
        <div class="left-wrap">
          <div class="loader"></div>
        </div>
        <div class="right-wrap">
          <div class="loader"></div>
        </div>
      </div>
    </div>
  </div>
</div>
sol
  • 22,311
  • 6
  • 42
  • 59
0

CSS Animation property will help you to rotate same animation in reverse.

//dont care about this code, its just to get the length of shapes to set the dash offset
let shape = document.querySelector('.circle');
let shapeLength= shape.getTotalLength();
console.log(shapeLength);
#circle { 
   width: 300px;
   height:300px;
   background: #fcfcfc;
}
.text{
   fill: red;
   text-anchor: middle;
}
#circle{
   animation: circleMove 5s ease-out infinite both alternate;
}
.circle{
   fill: none;
   stroke: red;
   stroke-width: 5px;
   stroke-dasharray:251;
   animation: circleMove 5s ease-in 1  alternate;
}
@keyframes circleMove{
   from{
      stroke-dashoffset: 251;
   }
   to{
      stroke-dashoffset: 0;
   }
}
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle -->

<div id="circle">
   <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
      <circle class='circle' cx="50" cy="50" r="40"/>
      <text class='text' x="50" y="50" font-family="Verdana" font-size="11" ></text>
   </svg>
</div>
Momin
  • 3,200
  • 3
  • 30
  • 48