CSS Circle Border Fill Animation

CSS circle border fill animation

You need to divide by 2 every values involved, even the clip(); ones (fiddle updated)

#loading {
width: 50px;
height: 50px;
margin: 30px auto;
position: relative;
}
.outer-shadow,
.inner-shadow {
z-index: 4;
position: absolute;
width: 100%;
height: 100%;
border-radius: 100%;
box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.5);
}
.inner-shadow {
top: 50%;
left: 50%;
width: 40px;
height: 40px;
margin-left: -20px;
margin-top: -20px;
border-radius: 100%;
background-color: #ffffff;
box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.5);
}
.hold {
position: absolute;
width: 100%;
height: 100%;
clip: rect(0px, 50px, 50px, 25px);
border-radius: 100%;
background-color: #fff;
}
.fill,
.dot span {
background-color: #f50;
}
.fill {
position: absolute;
width: 100%;
height: 100%;
border-radius: 100%;
clip: rect(0px, 25px, 50px, 0px);
}
.left .fill {
z-index: 1;
-webkit-animation: left 1s linear;
-moz-animation: left 1s linear;
animation: left 1s linear both;
}
@keyframes left {
0% {
-webkit-transform: rotate(0deg);
}
100% {
transform: rotate(180deg);
}
}
@-webkit-keyframes left {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(180deg);
}
}
.right {
z-index: 3;
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
transform: rotate(180deg);
}
.right .fill {
z-index: 3;
-webkit-animation: right 1s linear;
-moz-animation: right 1s linear;
animation: right 1s linear both;
-webkit-animation-delay: 1s;
-moz-animation-delay: 1s;
animation-delay: 1s;
}
@keyframes right {
0% {
-webkit-transform: rotate(0deg);
}
100% {
transform: rotate(180deg);
}
}
@-webkit-keyframes right {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(180deg);
}
}
.inner-shadow img {
margin-left: 8px;
margin-top: 7px;
}
<div id='loading'>
<div class='outer-shadow'>
</div>
<div class='inner-shadow'>
</div>
<div class='hold left'>
<div class='fill'></div>
</div>
<div class='hold right'>
<div class='fill'></div>
</div>

</div>

CSS animate circle border filling with color

There is a very easy to follow, informative and detailed tutorial on exactly how to achieve this (and more) by Anders Ingemann, which can be found here.

Its a fairly complex operation- so I'll simply distil the final stage from the tutorial here

Demo Fiddle

HTML

<div class="radial-progress">
<div class="circle">
<div class="mask full">
<div class="fill"></div>
</div>
<div class="mask half">
<div class="fill"></div>
<div class="fill fix"></div>
</div>
<div class="shadow"></div>
</div>
<div class="inset"></div>
</div>

CSS/LESS

.radial-progress {
@circle-size: 120px;
@circle-background: #d6dadc;
@circle-color: #97a71d;
@inset-size: 90px;
@inset-color: #fbfbfb;
@transition-length: 1s;
@shadow: 6px 6px 10px rgba(0, 0, 0, 0.2);
margin: 50px;
width: @circle-size;
height: @circle-size;
background-color: @circle-background;
border-radius: 50%;
.circle {
.mask, .fill, .shadow {
width: @circle-size;
height: @circle-size;
position: absolute;
border-radius: 50%;
}
.shadow {
box-shadow: @shadow inset;
}
.mask, .fill {
-webkit-backface-visibility: hidden;
transition: -webkit-transform @transition-length;
transition: -ms-transform @transition-length;
transition: transform @transition-length;
}
.mask {
clip: rect(0px, @circle-size, @circle-size, @circle-size/2);
.fill {
clip: rect(0px, @circle-size/2, @circle-size, 0px);
background-color: @circle-color;
}
}
}
.inset {
width: @inset-size;
height: @inset-size;
position: absolute;
margin-left: (@circle-size - @inset-size)/2;
margin-top: (@circle-size - @inset-size)/2;
background-color: @inset-color;
border-radius: 50%;
box-shadow: @shadow;
}
}

Example jQuery (could be substituted with CSS)

$('head style[type="text/css"]').attr('type', 'text/less');
less.refreshStyles();
var transform_styles = ['-webkit-transform', '-ms-transform', 'transform'];
window.randomize = function () {
var rotation = Math.floor(Math.random() * 180);
var fill_rotation = rotation;
var fix_rotation = rotation * 2;
for (i in transform_styles) {
$('.circle .fill, .circle .mask.full').css(transform_styles[i], 'rotate(' + fill_rotation + 'deg)');
$('.circle .fill.fix').css(transform_styles[i], 'rotate(' + fix_rotation + 'deg)');
}
}
setTimeout(window.randomize, 200);
$('.radial-progress').click(window.randomize);

Animating a circle border to fill up

There is a lot ways to do it, here are some

JS/Canvas:

  • http://p.ar2oor.pl/cprogress/
  • http://anthonyterrien.com/knob/

CSS3:

  • http://fromanegg.com/post/41302147556/100-pure-css-radial-progress-bar
  • http://www.alessioatzeni.com/blog/css3-loading-animation-loop/

SVG:

  • http://raphaeljs.com/

Filling a circle border by percent

For first linear part, you can use linear-gradient:(270deg,...) for filling 50% of the circle.

For other linear part, you can increase the angle (270°+) to fill more than 50% of the circle (360° or 0° = 75% of the circle ... 90° = 100% of the circle)

For example: linear-gradient(270deg, black 50%, transparent 50%), linear-gradient(0deg, black 50%, lightgray 50%) combination creates a circle with a lightgray background, filled with seventy-five percent black color. (snippet below)

.circle {  position: relative;  top: 5px;  left: 5px;  text-align: center;  width: 100px;  height: 100px;  border-radius: 100%;  background-color: #ffffff;}
.circle-border { position: relative; text-align: center; width: 110px; height: 110px; margin-left: 30%; border-radius: 100%; background-color: #E53B3B; background: linear-gradient(270deg, black 50%, transparent 50%), linear-gradient(0deg, black 50%, lightgray 50%)}
<div class="circle-border">  <div class="circle">  </div></div>

Circle to fill a container animation

You may use box-shadow instead transform and a pseudo a bit smaller to avoid the buggy gap around the container and the shadow;

$('#circle').on('click', (event) => {  $(event.currentTarget).toggleClass('clicked');});
body {}
#circle { width: 45px; height: 45px; border-radius: 50%; position: absolute; z-index: 999999999; top: 30px; left: 30px; background-color: black;}
#circle::before { content: ''; height: 28px; width: 28px; position: absolute; top: 3px; left: 3px; border-radius: inherit; transition: 0.75s ease; box-shadow: 0 0 0 0vw;}
#circle.clicked::before { box-shadow: 0 0 0 200vw;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body> <div id="circle"></div></body>

Hover effect in circle border

If I understand you correctly, here is one way you could make this work.

There are 3 elements to this; the image, the circle and the gap.

  • The circle is a div with a border-radius to round it out, and a border with the color of your choice.
  • The gap is a div that is the full height of the wrapper and the width of the intended gap. The div is given the same color as the background (white in this case - change to whatever you want). Then we apply a transform of -30deg to get the angle in your example.
  • The image is a div with a border-radius and is positioned in the middle of the wrapper.

The css then makes use of keyframes to add an animation to the gap div to make it rotate when you hover over the wrapper. This gives the illusion of the circle rotating.

.wrapper {
position: relative;
height: 350px;
width: 350px;
}

.wrapper .circle {
position: absolute;
height: 340px;
width: 340px;
border: 5px solid #00C17F;
border-radius: 50%;
}

.wrapper .gap {
position: absolute;
width: 100px;
height: 350px;
left: 125px;
background: white;
-ms-transform: rotate(-30deg);
-moz-transform: rotate(-30deg);
-webkit-transform: rotate(-30deg);
-o-transform: rotate(-30deg);
transform: rotate(-30deg);
}

.wrapper:hover .gap {
display: block;
-webkit-animation: rotateCircle 20s linear infinite;
-moz-animation: rotateCircle 20s linear infinite;
-ms-animation: rotateCircle 20s linear infinite;
-o-animation: rotateCircle 20s linear infinite;
animation: rotateCircle 20s linear infinite;
}

.wrapper .image {
position: absolute;
background-image: url("https://upload.wikimedia.org/wikipedia/commons/f/f2/Light_Work_%28Unsplash%29.jpg");
background-size: cover;
background-position: right;
border-radius: 50%;
top: 10%;
left: 10%;
height: 80%;
width: 80%;
}

@keyframes rotateCircle {
from {
-ms-transform: rotate(-30deg);
-moz-transform: rotate(-30deg);
-webkit-transform: rotate(-30deg);
-o-transform: rotate(-30deg);
transform: rotate(-30deg);
}

to {
-ms-transform: rotate(330deg);
-moz-transform: rotate(330deg);
-webkit-transform: rotate(330deg);
-o-transform: rotate(330deg);
transform: rotate(330deg);
}
}
<div class="wrapper">
<div class="circle"></div>
<div class="gap"></div>
<div class="image"></div>
</div>

Percentage circle border CSS React

Is don't think it's particularly a bug in your code - it's just that the system is trying to work out how to show part CSS pixels on a screen which uses several screen pixels per CSS pixel. Some can get 'left behind'.

A different way of creating the effect you want is to use background images made up of a conic gradient overlaid with a radial one (to give the 'hole' in the middle).

This is a simple snippet to demonstrate the idea in HTML/CSS. The CSS variable --ratio could be set in JS using setProperty to whatever the ratio of red to green is required.

.ratio {
--ratio: 0.3;
height: 150px;
width: 150px;
border-radius: 50%;
position: relative;
clip-path: circle(50%);
}

.ratio::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-image: conic-gradient(red 0 calc(var(--ratio) * 360deg), lime calc(var(--ratio) * 360deg) 360deg);
z-index: -2;
}

.ratio::after {
content: '';
position: absolute;
width: 80%;
height: 80%;
top: 10%;
left: 10%;
background-color: white;
border-radius: 50%;
z-index: -1;
}
<div class="ratio"></div>

Specific way to animate Circle Border with SVG?

That is, the gray lines should keep disappearing as they are now,
with the top disappearing at the same rate as the bottom. How do I do
this?

To do this, you must change the parameters of the stroke-dasharray attribute.

With a radius of a circle r = 49, the total circumference is 308

To make a symmetrical disappearance of a stroke with two lines from one point, you need to use two groups of parameters stroke-dasharray

values="154, 0 154, 0; 0, 308, 0, 0" where

154 - dash parameter of the first group stroke-dasharray

0 - gap parameter of the first group stroke-dasharray

As a result, the circle will be filled with a cavity at the first moment of the animation.

0, 308, 0, 0 - at this value, the length of the gap is maximum and the border of the circle becomes invisible

<svg height="200" width="200" viewBox="0 0 144 144">
<circle cx="72" cy="72" r="49"
stroke-width="6" stroke="#838588" fill="none">
<animate id="a" attributeName="stroke-dasharray" values="154, 0 154, 0; 0, 308, 0, 0" dur="2s" repeatCount="indefinite"/>
</circle>
</svg>


Related Topics



Leave a reply



Submit