Create and Filling arc progressively with css - circle progress bar - html

I'm struggling to fill an arc like a progress bar because I'm not that good working with css.
I want to achieve a "progress" arc like this:
I came across with this: https://codepen.io/enslavedeagle/pen/AXzaKE
#arc,
#arc::before {
display: block;
box-sizing: border-box;
border-radius: 100%;
width: 100px;
height: 100px;
position: absolute;
background-color: transparent;
padding: 0;
margin: 0;
}
#arc {
border: solid #00BBEE 12px;
clip: rect(0px, 100px, 50px, 0px);
margin: 25px;
}
#arc::before {
content: '';
border: solid black 12px;
top: -12px;
left: -12px;
clip: rect(0px, 100px, 50px, 0px);
transform: rotate(-150deg);
/* define the fill length, using the rotation above.
from -180deg (0% fill) to 0deg (100% fill) */
/* if you have a better solution to make thing like this
work, please let me know! :) */
}
and try to customize to be like what I want to but with no sucess until now: here: https://codepen.io/anon/pen/qpNrEP
Could any one give some help with this? Can also be alternative solution to achieve this.
I appreciate
Kind regards,

You can use an SVG with two arc on on top of the other and then use stroke-dash-array.
svg {
height: 90vh;
margin: auto;
display: block;
}
path {
stroke-linecap: round;
stroke-width: 2;
}
path.grey {
stroke: lightgrey;
}
path.purple {
stroke: purple;
stroke-dasharray: calc(40 * 3.142 * 1.85);
stroke-dashoffset: 20;
/* adjust last number for variance */
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 100 100">
<path class="grey" d="M40,90
A40,40 0 1,1 60,90"
style="fill:none;"/>
<path class="purple" d="M40,90
A40,40 0 1,1 60,90"
style="fill:none;"/>
</svg>

Using SVG is the best way to create an arc like this.
Here is the solution with all iterations of the loader:
.progress-wrapper {
height: 100vh;
display: flex;
align-items: center;
justify-content: space-around;
}
path {
stroke-linecap: round;
stroke-width: 6;
}
.grey {
stroke: #e5e5e5;
}
.red {
stroke: #e33800;
stroke-dasharray: 248;
stroke-dashoffset: 240;
/* adjust last number for variance */
}
.red-02 {
stroke-dashoffset: 220;
}
.red-03 {
stroke-dashoffset: 200;
}
.red-04 {
stroke-dashoffset: 180;
}
.red-05 {
stroke-dashoffset: 160;
}
.red-06 {
stroke-dashoffset: 140;
}
.red-07 {
stroke-dashoffset: 120;
}
.red-08 {
stroke-dashoffset: 100;
}
.red-09 {
stroke-dashoffset: 50;
}
.red-10 {
stroke-dashoffset: 0;
}
<div class="progress-wrapper">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
<path class="grey" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
<path class="red" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
<path class="grey" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
<path class="red red-02" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
<path class="grey" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
<path class="red red-03" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
<path class="grey" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
<path class="red red-04" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
<path class="grey" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
<path class="red red-05" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
<path class="grey" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
<path class="red red-06" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
<path class="grey" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
<path class="red red-07" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
<path class="grey" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
<path class="red red-08" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
<path class="grey" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
<path class="red red-09" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
<path class="grey" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
<path class="red red-10" d="M55,90
A55,55 0 1,1 140,90"
style="fill:none;"/>
</svg>
</div>
https://codepen.io/shalinigandhi/pen/mdmmwdV

I've just created a plnker in Angular 2 which I think it's exactly what you want.
It manage the fill of the second arc with a variable:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 100 100">
<path class="grey" d="M40,90 A40,40 0 1,1 60,90" style="fill:none;"/>
<path [ngStyle]="{'stroke-dashoffset':percentPath}" class="blue" d="M40,90 A40,40 0 1,1 60,90" style="fill:none;"/>
</svg>
Then, in the component I call a function which take the value from a slider with min=0 and max=100:
this.percentPath=(233-(V*2.33)); //233 is the maximun number stroke-dashoffset needs to disapear the second path
https://plnkr.co/edit/KNPThi?p=info
take it a look!

After not finding the answer I liked here I did some work myself and made a Codepen that you can use that makes progress bars exactly as you described with the inputs being: the amount of degrees of a circle that should be 100%, the radius of the circle and the percentage you to have filled.
Progress bar example (image)
HTML:
<section class="stat" id="sectionId">
<svg viewbox="0 0 100 100">
<path class="bar" d="
M 10, 50
a 40,40 0 1,0 80,0
a 40,40 0 1,0 -80,0
"/>
<path class="progress" d="
M 10, 50
a 40,40 0 1,0 80,0
a 40,40 0 1,0 -80,0
"/>
</svg>
<script type="text/javascript">
_.makeProgressBar("01", 240, 40, 86);
</script>
</section>
CSS:
.stat {
width: 200px;
}
svg {
display: block;
transform-origin: center center;
transform: rotate( 90deg );
}
path {
stroke-linecap: round;
stroke-width: 6px ;
fill:none;
}
JS:
_ = {};
//this is a self executing function, it keeps the global namespace clean
(function(win, doc, helper){
helper.makeProgressBar = function(id, totalDegrees, radius, percentage) {
var section = doc.getElementById(id);
var svg = section.children[0];
var bar = svg.children[0];
var progress = svg.children[1];
if(percentage > 100){
percentage = 100;
}
if(percentage < 0){
percentage = 0;
}
var percentageDegrees = calculateDegreesFromPercentage(totalDegrees, percentage);
var barDash = calculateDash(totalDegrees, radius);
var barGap = calculateDash ( 360 - totalDegrees, radius) * 2;
var progressDash = calculateDash(percentageDegrees, radius);
var progressGap = calculateDash(360 - percentageDegrees, radius) * 2;
var rotation = 0 - ((totalDegrees - percentageDegrees) / 2);
bar.setAttribute("style", "stroke: #707070; fill: none; stroke-dasharray: " + barDash + " " + barGap + ";");
progress.setAttribute("style", "stroke: #23CE39; fill: none; stroke-dasharray: " + progressDash + " " + progressGap + "; transform-origin: center center; transform: rotate("+ rotation +"deg)");
}
calculateDegreesFromPercentage = function(totalDegrees, percentage) {
return totalDegrees/100*percentage;
}
calculateDash = function(degrees, radius) {
return degrees * Math.PI / 180 * 0.5 * radius;
}
})(window, document, _);

Related

CSS transition-property for rotate3d does not work on SVGs

I'm having trouble using a transition-property for rotate3d. It works with all but not with rotate or rotate3d.
Is there any way to single out rotate or rotate3d so I can use other transforms without easing?
.lock-animation {
width:6em;
margin:2em auto;
overflow:visible;
}
.lock-animation svg {
overflow:visible;
}
.lock-animation g#lock-top{
transition: rotate 0.3s ease-in-out;
}
.lock-animation:hover g#lock-top {
transform: translateX(150%) rotate3d(0, 1, 0, -180deg);
}
<div class="lock-animation">
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 448 512" enable-background="new 0 0 448 512" xml:space="preserve">
<g id="lock-bottom" focusable="false">
<g>
<path fill="none" d="M224,48c-52.9,0-96,43.1-96,96v48h192v-48C320,91.1,276.9,48,224,48z"/>
<path fill="none" d="M48,464h352V240H48V464z M196,320c0-15.5,12.5-28,28-28s28,12.5,28,28v64c0,15.5-12.5,28-28,28
s-28-12.5-28-28V320z"/>
<path d="M224,412c15.5,0,28-12.5,28-28v-64c0-15.5-12.5-28-28-28s-28,12.5-28,28v64C196,399.5,208.5,412,224,412z"/>
<path d="M400,192h-32h-48H128H80H48c-26.5,0-48,21.5-48,48v224c0,26.5,21.5,48,48,48h352c26.5,0,48-21.5,48-48V240
C448,213.5,426.5,192,400,192z M400,464H48V240h352V464z"/>
</g>
</g>
<g id="lock-top">
<path d="M223.7,0C303.2-0.2,368,64.5,368,144v48h-48v-46.8c0-52.8-42.1-96.7-95-97.2c-53.4-0.6-97,42.7-97,96v56
c0,13.3-10.7,24-24,24s-24-10.7-24-24v-54.6C80,65.8,144,0.2,223.7,0z"/>
</g>
</svg>
</div>
You need to adjust the transform-origin then you can get rid of the translate and apply transition to transform that contains only rotate
.lock-animation {
width: 6em;
margin: 2em auto;
overflow: visible;
}
.lock-animation svg {
overflow: visible;
}
.lock-animation g#lock-top {
transition: transform 0.3s ease-in-out;
transform-origin: 90% 0;
transform-box: fill-box;
}
.lock-animation:hover g#lock-top {
transform: rotate3d(0, 1, 0, -180deg);
}
<div class="lock-animation">
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 448 512" enable-background="new 0 0 448 512" xml:space="preserve">
<g id="lock-bottom" focusable="false">
<g>
<path fill="none" d="M224,48c-52.9,0-96,43.1-96,96v48h192v-48C320,91.1,276.9,48,224,48z"/>
<path fill="none" d="M48,464h352V240H48V464z M196,320c0-15.5,12.5-28,28-28s28,12.5,28,28v64c0,15.5-12.5,28-28,28
s-28-12.5-28-28V320z"/>
<path d="M224,412c15.5,0,28-12.5,28-28v-64c0-15.5-12.5-28-28-28s-28,12.5-28,28v64C196,399.5,208.5,412,224,412z"/>
<path d="M400,192h-32h-48H128H80H48c-26.5,0-48,21.5-48,48v224c0,26.5,21.5,48,48,48h352c26.5,0,48-21.5,48-48V240
C448,213.5,426.5,192,400,192z M400,464H48V240h352V464z"/>
</g>
</g>
<g id="lock-top">
<path d="M223.7,0C303.2-0.2,368,64.5,368,144v48h-48v-46.8c0-52.8-42.1-96.7-95-97.2c-53.4-0.6-97,42.7-97,96v56
c0,13.3-10.7,24-24,24s-24-10.7-24-24v-54.6C80,65.8,144,0.2,223.7,0z"/>
</g>
</svg>
</div>

my svg stops at some point with the animation

I have the SVG element (see below) that animates but after some time it stops animating. I would like that the animation continues like this jsfiddle.
.path {
stroke-dasharray: 20;
animation: dash 10s linear;
}
#keyframes dash {
to {
stroke-dashoffset: 1000;
}
}
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="340px"
height="333px" viewBox="0 0 340 333" enable-background="new 0 0 340 333"
xml:space="preserve">
<path class="path" fill="#fff" stroke="#000" stroke-width="2"
d="m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-
1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2
1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z"/>
</svg>
All you're missing is the infinite keyword. Refer to the docs for more.
.path {
stroke-dasharray: 20;
animation: dash 10s linear infinite;
}
#keyframes dash {
to {
stroke-dashoffset: 1000;
}
}
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="340px"
height="333px" viewBox="0 0 340 333" enable-background="new 0 0 340 333"
xml:space="preserve">
<path class="path" fill="#fff" stroke="#000" stroke-width="2"
d="m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-
1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2
1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z"/>
</svg>

Inverse transparent area in SVG

I have this SVG :
<svg class="decor" height="100%" preserveAspectRatio="none" version="1.1" viewBox="0 0 100 100" width="100%" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0 L50 100 L100 0 L100 100 L0 100" stroke-width="0"></path>
</svg>
This works but I need to have transparent outer and black color inner. In my code this is currently inverse.
How to generate this?
DEMO
Just change the coordinates of your SVG path (d attribute) to form a triangle instead of the shape.
The modified path (d="M0 0 L50 100 L100 0z") works as follow:
M0 0 - Moves the pen to 0,0 (top left corner)
L 50 100 - Draws a line from 0,0 to 50,100 (which is bottom center point)
L 100 0 - Draws a line from 50,100 to 100 0 (which is top right corner)
z - Closes the path by drawing a line from the last point (100,0) to the first point (0,0)
SVG path elements by default get a black colored fill and hence the triangle gets colored black whereas the outside remains transparent.
* {
background: #e1e1e1;
}
.decor {
height: 80px
}
<div class="decor">
<svg class="decor" height="100%" preserveAspectRatio="none" version="1.1" viewBox="0 0 100 100" width="100%" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0 L50 100 L100 0z" stroke-width="0"></path>
</svg>
</div>
Clip Image using Path:
If the need is to use the path to clip background image into the required shape then it would be better to use clipPath element and clip-path CSS property like in the below snippet:
* {
background: #e1e1e1;
}
.decor {
height: 80px;
background: url(http://lorempixel.com/200/80);
-webkit-clip-path: url(#clipper);
clip-path: url(#clipper);
}
<div class="decor">
<svg height="0" preserveAspectRatio="none" version="1.1" viewBox="0 0 100 100" width="0" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="clipper" clipPathUnits="objectBoundingBox">
<path d="M0 0 L.5 1 L1 0z"></path>
</clipPath>
</defs>
</svg>
</div>
Putting all the pieces together, the below code should achieve the output that was provided in the image.
.div-1 {
position: relative;
height: 500px;
width: 100%;
}
.decor-top {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('http://lorempixel.com/550/500');
-webkit-clip-path: url(#clipper);
clip-path: url(#clipper);
}
.div-2 {
position: absolute;
bottom: 0;
left: 0;
height: 50%;
width: 100%;
background-image: url('http://kinderhtml.themerex.net/img/bg/texture_2.png');
background-color: green;
-webkit-clip-path: url(#clipper2);
clip-path: url(#clipper2);
}
<div class="div-1">
<div class="decor-top">
<svg height="0" preserveAspectRatio="none" version="1.1" viewBox="0 0 100 100" width="0" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="clipper" clipPathUnits="objectBoundingBox">
<path d="M0 0 L.5 .1 L1 0 1,1 0,1z"></path>
</clipPath>
</defs>
</svg>
</div>
<div class="div-2">
<svg height="0" preserveAspectRatio="none" version="1.1" viewBox="0 0 100 100" width="0" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="clipper2" clipPathUnits="objectBoundingBox">
<path d="M0 0 L.5 .25 L1 0 1,1 0,1z"></path>
</clipPath>
</defs>
</svg>
</div>
</div>
The original path (d="M0 0 L50 100 L100 0 L100 100 L0 100") worked as follows:
M0 0 - Moves the pen to 0,0 (top left corner)
L 50 100 - Draws a line from 0,0 to 50,100 (which is bottom center point)
L 100 0 - Draws a line from 50,100 to 100 0 (which is top right corner)
L 100 100 - Draws a line from 100,0 to 100,100 (which is bottom right corner)
L0 100 - Draws a line from 100,100 to 0,100 (which is bottom left corner)
Thus the above path ends up a forming a shape which looks like a rectangle with a triangle cut-out at the top.

rotate svg fill path box

I design box border using svg like this :
HTML:
<svg class="decor" height="100%" preserveaspectratio="none" version="1.1" viewbox="0 0 100 100" width="100%" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0 L100 100 L0 100" stroke-width="0"></path>
</svg>
CSS:
.decor {
fill: #F00;
stroke: #e74c3c;
}
result:
Now i need to rotation to this:
How do generate this?!
DEMO FIDDLE
Add transform="rotate(180, 50, 50)" to the path
.decor {
fill: #F00;
stroke: #e74c3c;
}
<svg class="decor" height="100%" viewBox="0 0 100 100" width="100%" preserveAspectRatio="none" >
<path transform="rotate(180, 50, 50)" d="M0 0 L100 100 L0 100"></path>
</svg>
Just do this:
.decor {
fill: #F00;
stroke: #e74c3c;
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
This will rotate it to be the way you want.
Fiddle: http://jsfiddle.net/jkvp1x8m/

Make SVG path take full width and height of screen

I have an inline SVG path that animates a dash to look like the snake game. Now my question is how to get this path to take up the full width and height of the screen and act responsive if the screen goes smaller or bigger.
HTML
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100%" height="100%" viewBox="0 0 659 522" enable-background="new 0 0 659 522" xml:space="preserve">
<path class="path" width="100%" height="100%" fill="none" stroke="#00ff00" stroke-width="5" stroke-miterlimit="10" d="M656.5,2.5v517H2.5V2.5H656.5z"
stroke-dasharray="2042 300"
stroke-dashoffset="2342" />
</svg>
CSS
.path {
animation: dash 10s linear infinite;
}
#-webkit-keyframes dash {
to {
stroke-dashoffset: 0;
}
}
Here is a fiddle with the code I have.
http://jsfiddle.net/c3ar6e5o/
You have to tell the SVG not to maintain its aspect ratio with preserveAspectRatio="none" in the SVG code..then it's just CSS.
JSfiddle Demo
html,
body {
margin: 0;
height: 100%;
}
svg {
display: block;
}
.path {
animation: dash 10s linear infinite;
}
#-webkit-keyframes dash {
to {
stroke-dashoffset: 0;
}
}
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100%" height="100%" viewBox="0 0 659 522" enable-background="new 0 0 659 522" xml:space="preserve" preserveAspectRatio="none">
<path class="path" width="100%" height="100%" fill="none" stroke="#00ff00" stroke-width="5" stroke-miterlimit="10" d="M656.5,2.5v517H2.5V2.5H656.5z" stroke-dasharray="2042 300" stroke-dashoffset="2342" />
</svg>