Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing animated arc with pure CSS

I know it is possible to draw and animate arcs in SVG and canvas. However, is it possible in CSS?

I have created an arc using the following method:

.arc{
    width:150px;
    height:400px;
    border-radius:50%;
    border-right:1px solid black;
    border-left:1px solid black;
    border-top:1px solid black;
    border-bottom:1px solid white;
}

But, how can I animate this? The only way I can think of is having a pure white div over it and sliding that div to the right gradually revealing the arc. Is there a better way?

like image 875
Conqueror Avatar asked Sep 16 '13 19:09

Conqueror


People also ask

Is it possible to draw a circular progress arc with SVG?

It’s tempting to resort to SVG, but that brings with it scaling trickery which we can avoid by sticking with pure HTML. In this tutorial, we’ll show you a trick to draw a circular progress arc using skew transformations.

How do I animate a circle around an element?

The easiest method I know of to achieve this is to “layer” the animation movement: moving an element up and down in half the phase that it moves in a circle. To achieve this, the element is wrapped inside a container: And each element animated separately:

How to turn a circle into an arc in Photoshop?

With four copies of the rectangle, rotated by 0°, 90°, 180° and 270°, we can cover a complete circle. That way, we can set their skew degrees individually and draw any arc from 0° to 360° By overlaying a smaller inner circle on the main circle, we can turn our circle into an arc, and we’ll have a place to print the progress value.

How do I draw circular shapes in CSS?

Drawing circular shapes in CSS is hard, since the only way to do so is by using border-radius: 50%, which only gets you so far - in particular when you’re trying to draw arcs. It’s tempting to resort to SVG, but that brings with it scaling trickery which we can avoid by sticking with pure HTML.


1 Answers

Here is working demo with minimum of hard-coded variables. This works based on animated circle halves:

.circle {
  display: inline-flex;
  overflow: hidden;
}

.circle__half {
  height: 200px;
  width: 100px;
  position: relative;
  overflow: hidden;
}

.circle__half:before {
  height: inherit;
  width: inherit;
  position: absolute;
  content: "";
  border-radius: 100px 0 0 100px;
  background-color: lime;
  transform-origin: 100% 50%;
  /* hidden by default */
  transform: rotate(180deg);
  opacity: 0.65;
  animation-name: rotate-circle-half;
  animation-duration: 4s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

.circle__half--right {
  transform: scale(-1, -1);
}

.circle .circle__half--right:before {
  animation-name: rotate-circle-half--right;
}

/* show half of circle half of the time */
@keyframes rotate-circle-half {
  0% {
    transform: rotate(180deg);
  }
  50% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

@keyframes rotate-circle-half--right {
  0% {
    transform: rotate(180deg);
  }
  50% {
    transform: rotate(180deg);
  }
  100% {
    transform: rotate(0deg);
  }
}
<div class="circle">
  <div class="circle__half"></div>
  <div class="circle__half circle__half--right"></div>
</div>

Also the same look as iConnor's answer but doesn't have drawback of hardcoded background-color:

*,
*:before,
*:after {
  box-sizing: border-box;
}

.circle {
  display: inline-flex;
  overflow: hidden;
}

.circle__half {
  height: 200px;
  width: 100px;
  position: relative;
  overflow: hidden;
}

.circle__half:before {
  height: inherit;
  width: inherit;
  position: absolute;
  content: "";
  border-radius: 100px 0 0 100px;
  border: 10px solid #00507c;
  border-right-color: transparent;
  background-color: #0087cf;
  transform-origin: 100% 50%;
  /* hidden by default */
  transform: rotate(180deg);
  opacity: 0.65;
  animation-name: rotate-circle-half;
  animation-duration: 4s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

.circle__half--right {
  transform: scale(-1, -1);
}

.circle .circle__half--right:before {
  animation-name: rotate-circle-half--right;
}

/* show half of circle half of the time */
@keyframes rotate-circle-half {
  0% {
    transform: rotate(180deg);
  }
  50% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

@keyframes rotate-circle-half--right {
  0% {
    transform: rotate(180deg);
  }
  50% {
    transform: rotate(180deg);
  }
  100% {
    transform: rotate(0deg);
  }
}
<div class="circle">
  <div class="circle__half"></div>
  <div class="circle__half circle__half--right"></div>
</div>
like image 110
Vadim Ovchinnikov Avatar answered Sep 23 '22 02:09

Vadim Ovchinnikov