Drawing Animated Arc with Pure CSS

SVG semi-arc clockwise animation over 180 degrees (half of a circle) with pure CSS/JS

A possible solution would be animating a very thick stroke (the double of the radius of the circle).

In this case the radius of the circle is 20 so the stroke-width="40"

In the next example I'm animating the stroke-dasharray of the path from: 62.84,0 (stroke length = 62.84, gap = 0) to 0, 62.4 (stroke length = 0, gap = 62.84) where 62.84 is the length of the path.

Please read about how How SVG Line Animation Works

path {
stroke-dasharray: 62.84,0;
animation: anim 5s linear infinite;
}

@keyframes anim {
to {
stroke-dasharray: 0, 62.84;
}
}
<svg viewBox="-50 -50 100 100" width="90vh">
<path stroke-width="40" fill="none" stroke="black" d="M20,0A20,20 0 0 0 -20,0"/>
</svg>

Draw and erase arcs - Arc animation using JavaScript or CSS

For the canvas version, as stated in comments, your antialiasing problem is that you are redrawing over and over on the same pixels.

To avoid this, clear your whole canvas every frame and redraw everything.


For your requested animation, you would have to store both your start angle and your end angle. Then you'll increment one after the other, while swithing when you've passed the division size threshold.

Here is an annotated snippet that will make things more clear I hope.

// settingsvar divisions = 3;var duration = 3000; // in msvar canvas = document.getElementById("canvas1");var context = canvas.getContext("2d");var x = canvas.width / 2;var y = canvas.height / 2;var radius = (canvas.width / 7) * 2;context.lineWidth = 4;
// initvar currentSplit = 0;var splitAngle = (Math.PI * 2) / divisions;var splitTime = (duration / (divisions*2)); // how much time per split per endvar angles = [0,0]; // here we store both start and end anglevar current = 0;var startTime = performance.now();draw();
function draw(currentTime) { // first convert the elapsed time to an angle var timedAngle = ((currentTime - startTime) / splitTime) * splitAngle; // set the current end to this timed angle + the current position on the circle angles[current] = timedAngle + (splitAngle * currentSplit);
if (timedAngle >= splitAngle) { // one split is done for this end // it should not go farther than the threshold angles[current] = (splitAngle * (currentSplit + 1)); current = +(!current) // switch which end should move startTime = currentTime; // reset the timer
if(!current){ // we go back to the start currentSplit = (currentSplit + 1) % divisions; // increment our split index } }
if(angles[1] > Math.PI*2){ // we finished one complete revolution angles[0] = angles[1] = current = 0; // reset everything } // at every frame we clear everything context.clearRect(0, 0, canvas.width, canvas.height); // and redraw context.beginPath(); context.arc(x, y, radius, angles[0], angles[1], true); context.stroke();
requestAnimationFrame(draw); // loop at screen refresh rate}
body {  text-align: center;}
#canvas1 { width: 250px; height: 150px;}
<canvas id="canvas1" width="500" height="300"></canvas>

CSS arc rounded at the ends

http://jsfiddle.net/k6d17fez/1/

Okay, so I ripped off part of this already working solution and added these two blocks of code:

.wrapper::after{
content:'';
display:block;
width:5px;
height:5px;
background:#004466;
border-radius:50%;
position:relative;
left:123px;
z-index:1000;
}

.wrapper .spinner::after{
content:'';
display:block;
width:5px;
height:5px;
background:#004466;
border-radius:50%;
position:relative;
left:118px;
top:-5px;
z-index:1000;
}

It essentially adds two little circles at the ends of the circumference of the pie.

This is what it looks like in Firefox 37.0.1:

Rounded Corners

This solution may be a little bit “quick and dirty” but it does the job. Of course Canvas is far more suitable for this.

Css animation across an Arc

I've forked the (very good) @ArunBertil "fulcrum" solution to convert it to CSS3 Animation:

Running Demo

CSS

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

@keyframes drawArc2 {
0% { transform: rotate(-180deg); }
100% { transform: rotate(0deg); }
}

body{
padding: 150px;
background: black;
}

.wrapper {
width: 300px;
animation: drawArc1 3s linear infinite;
}

.inner {
border-radius: 50%;
display: inline-block;
padding: 30px;
background: yellowgreen;
animation: drawArc2 3s linear infinite;
}

HTML

<div class="wrapper">
<div class="inner"></div>
</div>

Watch it on FireFox... to run it on other browsers, simply put the prefixes (@-webkit-keyframes, etc)

Animated canvas arc with easing

It is a mater of math:

drawRing(384, 384, 384, 20, seconds / 60, 3 / 2 * Math.PI, false);

This is the line which is drawing the seconds circle. So the problem is that in any given moment you have something like 34/60, 35/60 and so on. This means your seconds circle is 60/60 thus not using the milliseconds, and drawing it each second.

The linear easing solution: make your seconds circle 60 000 / 60 000 -> 60 seconds by 1000 millisecond each. And the math:

drawRing(384, 384, 384, 20, ((seconds*1000)+milliseconds) / 60000, 3 / 2 * Math.PI, false);

The In Out Quadric solution or choose one these :

Math.easeInOutQuad = function (t, b, c, d) {
t /= d/2;
if (t < 1) return c/2*t*t + b;
t--;
return -c/2 * (t*(t-2) - 1) + b;
};

And I optimized and changed your code:

//+1 animation happens before the second hand
//-1 animation happens after the second hand
animatedSeconds = seconds+1;
if (milliseconds > 10) {
if (!startValue) { startValue = milliseconds; }
if (milliseconds - startValue <= 100) {
animatedSeconds -= -0.5+ Math.easeInOutQuad(milliseconds - startValue, startValue, 1000 - startValue, 125) / 1000;
}
} else {
startValue = 0;
}
drawRing(384, 384, 384, 20, animatedSeconds / 60, 3 / 2 * Math.PI, false);

Hopefully this is what you are looking for.

CSS ONLY Animate Draw Circle with border-radius and transparent background

This is my solution.

I set a background on body to show it is transparent

body {  background: repeating-linear-gradient(45deg, white 0px, lightblue 100px);  height: 500px;  background-size: 500px 500px;  background-repeat: no-repeat;}
html { height: 100%;}
#container { position: absolute; width: 400px; height: 400px; border: solid red 1px; animation: colors 4s infinite;}
#halfclip { width: 50%; height: 100%; right: 0px; position: absolute; overflow: hidden; transform-origin: left center; animation: cliprotate 16s steps(2) infinite; -webkit-animation: cliprotate 16s steps(2) infinite;}
.halfcircle { box-sizing: border-box; height: 100%; right: 0px; position: absolute; border: solid 25px transparent; border-top-color: blue; border-left-color: blue; border-radius: 50%;}#clipped { width: 200%; animation: rotate 8s linear infinite; -webkit-animation: rotate 8s linear infinite;}#fixed { width: 100%; transform: rotate(135deg); animation: showfixed 16s steps(2) infinite; -webkit-animation: showfixed 16s linear infinite;}
@-webkit-keyframes cliprotate { 0% {transform: rotate(0deg);} 100% {transform: rotate(360deg);}}
@keyframes cliprotate { 0% {transform: rotate(0deg);} 100% {transform: rotate(360deg);}}

@-webkit-keyframes rotate { 0% {transform: rotate(-45deg);} 100% {transform: rotate(135deg);}}
@keyframes rotate { 0% {transform: rotate(-45deg);} 100% {transform: rotate(135deg);}}
@-webkit-keyframes showfixed { 0% {opacity: 0;} 49.9% {opacity: 0;} 50% {opacity: 1;} 100% {opacity: 1;}}
<div id="container">    <div id="halfclip">        <div class="halfcircle" id="clipped">        </div>    </div>    <div class="halfcircle" id="fixed">    </div></div>

Is it possible to draw a partial circle outline in CSS (open ring shape)?

To create a circle that gradually draws it's outer path, use SVG.

SVG's stroke-dasharray property will turn any path into a dashed line, which you can use to your advantage by setting the dash size to be almost as long as the path itself.

Then use a CSS animation to gradually change the stroke-dashoffset to move the dash around the perimeter of your circle.

circle {  fill: white;  stroke: black;  stroke-width: 2;  stroke-dasharray: 250;  stroke-dashoffset: 1000;  animation: rotate 5s linear infinite;}
@keyframes rotate { to { stroke-dashoffset: 0; }}
<svg height="100" width="100">  <circle cx="50" cy="50" r="40" /></svg>

How to draw a circle sector in CSS?

CSS and Multiple Background Gradients

Rather than trying to draw the green portion, you could draw the white portions instead:

pie {
border-radius: 50%;
background-color: green;
}

.ten {
background-image:
/* 10% = 126deg = 90 + ( 360 * .1 ) */
linear-gradient(126deg, transparent 50%, white 50%),
linear-gradient(90deg, white 50%, transparent 50%);
}

pie {
width: 5em;
height: 5em;
display: block;
border-radius: 50%;
background-color: green;
border: 2px solid green;
float: left;
margin: 1em;
}

.ten {
background-image: linear-gradient(126deg, transparent 50%, white 50%), linear-gradient(90deg, white 50%, transparent 50%);
}

.twentyfive {
background-image: linear-gradient(180deg, transparent 50%, white 50%), linear-gradient(90deg, white 50%, transparent 50%);
}

.fifty {
background-image: linear-gradient(90deg, white 50%, transparent 50%);
}

/* Slices greater than 50% require first gradient
to be transparent -> green */

.seventyfive {
background-image: linear-gradient(180deg, transparent 50%, green 50%), linear-gradient(90deg, white 50%, transparent 50%);
}

.onehundred {
background-image: none;
}
<pie class="ten"></pie>
<pie class="twentyfive"></pie>
<pie class="fifty"></pie>
<pie class="seventyfive"></pie>
<pie class="onehundred"></pie>


Related Topics



Leave a reply



Submit