0

I am trying to create the same animation as illustrated in the following:

body {
 text-align: center;
 background: #222;
}

svg {
 position: absolute;
 display: block;
}

.container {
 display: inline-block;
 position: relative;
 width: 50px;
}

.container #Layer_2 {
 width: 60px;
 stroke-dasharray: 121;
 stroke-dashoffset: 121;
 transform: rotate(270deg);
}

.container #Layer_2.on {
 animation: circle 1.4s;
 -webkit-animation-fill-mode: forwards;
 animation-fill-mode: forwards;
}

@keyframes circle {
 0% {
  stroke-dashoffset: 121;
  transform: rotate(90deg);
 }

 100% {
  stroke-dashoffset: 0;
 }
}
<div class="container">

  <svg id="Layer_2" class="on" viewBox="0 0 50 50">
    <defs>
      <style>
        .cls-1 {
          fill: none;
          stroke: #ddd;
          stroke-miterlimit: 10;
          stroke-width: 1px;
        }

      </style>
    </defs>
    <circle class="cls-1" cx="25" cy="25" r="19.27" />
  </svg>

</div>

However, I ideally don't want to use an SVG. I have already got a spinner on my site that uses a similar animation:

* {
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale;
 box-sizing: border-box;
 font-family: "Avenir Next", sans-serif;
 margin: 0;
 outline: none;
 padding: 0;
}

.spinner-wrapper {
 display: inline-block;
 position: relative;
 width: 64px;
 height: 64px;
 animation: wrapper-rotate 1568ms linear infinite;
 --spinner-border-width: 3px;
 --spinner-color: black;
}

.spinner-wrapper .spinner {
 position: absolute;
 width: 100%;
 height: 100%;
 animation: fill-unfill-rotate 5332ms cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite both;
}

.spinner-wrapper .circle-clipper {
 display: block;
 position: relative;
 width: 50%;
 height: 100%;
 float: left;
 overflow: hidden;
}

.spinner-wrapper .circle-clipper.circle-clipper-left .circle {
 left: 0;
 border-right-color: transparent !important;
 transform: rotate(129deg);
 animation: left-spin 1333ms cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite both;
}

.spinner-wrapper .circle-clipper.circle-clipper-right .circle {
 right: 0;
 border-left-color: transparent !important;
 transform: rotate(-129deg);
 animation: right-spin 1333ms cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite both;
}

.spinner-wrapper .circle-clipper .circle {
 position: absolute;
 top: 0;
 right: 0;
 bottom: 0;
 width: 200%;
 height: 100%;
 border: var(--spinner-border-width) solid var(--spinner-color);
 border-bottom-color: transparent !important;
 border-radius: 50%;
}

.spinner-wrapper .gap-patch {
 position: absolute;
 top: 0;
 left: 45%;
 width: 10%;
 height: 100%;
 overflow: hidden;
}

.spinner-wrapper .gap-patch .circle {
 width: 1000%;
 left: -450%;
}

@keyframes wrapper-rotate {
 to {
  transform: rotate(360deg);
 }
}

@keyframes fill-unfill-rotate {
 12.5% {
  transform: rotate(135deg);
 }

 25% {
  transform: rotate(270deg);
 }

 37.5% {
  transform: rotate(405deg);
 }

 50% {
  transform: rotate(540deg);
 }

 62.5% {
  transform: rotate(675deg);
 }

 75% {
  transform: rotate(810deg);
 }

 87.5% {
  transform: rotate(945deg);
 }

 to {
  transform: rotate(1080deg);
 }
}

@keyframes left-spin {
 from {
  transform: rotate(130deg);
 }

 50% {
  transform: rotate(-5deg);
 }

 to {
  transform: rotate(130deg);
 }
}

@keyframes right-spin {
 from {
  transform: rotate(-130deg);
 }

 50% {
  transform: rotate(5deg);
 }

 to {
  transform: rotate(-130deg);
 }
}
<div class="spinner-wrapper">
    <div class="spinner">
      <div class="circle-clipper circle-clipper-left">
        <div class="circle"></div>
      </div>
      <div class="gap-patch circle-clipper">
        <div class="circle"></div>
      </div>
      <div class="circle-clipper circle-clipper-right">
        <div class="circle"></div>
      </div>
    </div>
  </div>

The animation illustrated above is similar to what I want to achieve but obviously it is infinite and doesn't quite complete the full circle.

Can anyone suggest what I can do to my existing solution in order to adapt it to imitate the first animation?

I have tried various things but have not been able to make any real progress.

Ben Carey
  • 16,540
  • 19
  • 87
  • 169
  • I know that you explicitly asked to adapt your existing code, but are you open to a new code instead (that has the desired behaviour)? – Richard Apr 26 '20 at 04:01
  • @Richard Of course :-D!I just want to avoid the SVG implementation... – Ben Carey Apr 26 '20 at 08:23

1 Answers1

1

I will consider an idea using clip-path like I did in this previous answer:

.loader {
  width:150px;
  height:150px;
  display:inline-block;
  margin:20px;
  border:2px solid #fff;
  border-radius:50%;
  transform:scaleX(var(--s,1)) rotate(225deg);
  clip-path:polygon(50% 50%,0 0,0 0,0 0, 0 0,0 0);
  animation:change 1.4s linear forwards;
}
.opp {
  --s:-1;
}

@keyframes change {
  25% {
    clip-path:polygon(50% 50%,0 0,   0 100%,0 100%,0 100%,0 100%);
  }
  50% {
    clip-path:polygon(50% 50%,0 0,0 100%,   100% 100%, 100% 100%,100% 100%);
  }
  75% {
    clip-path:polygon(50% 50%,0 0,0 100%,100% 100%,    100% 0,100% 0);
  }
  100% {
    clip-path:polygon(50% 50%,0 0,0 100%,100% 100%, 100% 0,     0% 0%);
    transform:scaleX(var(--s,1)) rotate(45deg);
  }
}

body {
 background:black;
}
<div class="loader"></div>

<div class="loader opp"></div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415