This question already has answers here:
CSS Progress Circle
(8 answers)
Closed 4 years ago.
I try to design a circle progressbar with some information inside. Something like this.
I have svg but I cant write inside circle also. The start and end point distance is very low. I am looking for something like image.
svg {
height: 200px;
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: 80;
/ 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 70,90"
style="fill:none;"/>
<path class="purple" d="M40,90
A40,40 0 1,1 70,90"
style="fill:none;"/>
</svg>
This is my solution; In order to calculate the path's length you may use the path.getTotalLength() method.
In order to center the text around a point (the center of the SVG canvas in this case) use dominant-baseline="middle" text-anchor="middle"
theRange.addEventListener("input",()=>{
let v=220.6 - map(theRange.value,0,100,0,220.6);
thePath.style.strokeDashoffset = v
theText.textContent = theRange.value+"%"
})
function map(n, a, b, _a, _b) {
let d = b - a;
let _d = _b - _a;
let u = _d / d;
return _a + n * u;
}
svg {
height: 200px;
margin: auto;
display: block;
border:1px solid;
overflow:visible
}
path {
stroke-linecap: round;
stroke-width: 2;
}
.grey {
stroke: lightgrey;
}
.purple {
stroke: purple;
stroke-dasharray: 220.6;
stroke-dashoffset: 44.12;
}
p{text-align:center}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 110 110">
<defs>
<path id="thePath" d="M40,90
A40,40 0 1,1 70,90"
style="fill:none;"/>
</defs>
<use xlink:href="#thePath" id="base" class="grey" />
<use xlink:href="#thePath" id="slider" class="purple" />
<text id="theText" x="55" y="55" dominant-baseline="middle" text-anchor="middle">80%</text>
</svg>
<p><input id="theRange" type="range" min="0" max="100" value="80" step=".1" /></p>
I tried copying my SVG into my HTML and defining it as a clipPath, but it doesn't display the shape the right way. Can I define clipPath using a file path?
<div class="gradient">
</div>
<svg height="0" width="0">
<defs>
<clipPath id="Camera">
<style>
.cls-1, .cls-2 {
fill: #363636;
}
.cls-1, .cls-3 {
stroke: #363636;
}
.cls-1 {
stroke-width: 1px;
fill-rule: evenodd;
}
.cls-3 {
fill: none;
stroke-width: 50px;
}
</style>
<path class="cls-1" d="M566.282,395.982s-121.771,16.243-155.258,35.532-93.7,51.606-135.978,123.854c-1.285-10.084-1.014-8.122-1.014-8.122v-33.5a319.278,319.278,0,0,1,20.3-80.2c15.223-37.882,41.848-78.09,77.121-99.489,55.447,0,87.691,5.262,142.067,27.411C565.1,395.035,566.282,395.982,566.282,395.982Zm-136.671,44.24S382.787,553.845,382.741,592.5s-2.176,106.981,39.225,179.738c-9.372-3.929-7.538-3.182-7.538-3.182l-29-16.751a319.037,319.037,0,0,1-59.278-57.684c-25.181-32.13-46.675-75.3-47.563-116.562,27.724-48.04,48.4-73.345,94.761-109.381C428.2,440.773,429.611,440.222,429.611,440.222Zm-34.372,138.5s74.972,97.311,108.424,116.665,91.55,55.336,175.261,55.844c-8.09,6.151-6.526,4.936-6.526,4.936l-29.01,16.739a319.273,319.273,0,0,1-79.6,22.5c-40.418,5.748-88.553,2.786-124.725-17.061-27.733-48-39.3-78.549-47.321-136.692C395.011,580.218,395.239,578.721,395.239,578.721ZM501.768,677.28s121.722-16.3,155.2-35.605,93.676-51.652,135.971-123.924c1.28,10.084,1.011,8.121,1.011,8.121l-0.015,33.5a319.666,319.666,0,0,1-20.323,80.215c-15.233,37.892-41.864,78.115-77.131,99.532-55.422.025-87.649-5.222-141.989-27.348C502.95,678.227,501.768,677.28,501.768,677.28Zm138.679-42.488s46.752-113.61,46.78-152.27,2.126-106.987-39.29-179.768c9.37,3.933,7.536,3.185,7.536,3.185l29,16.765a319.457,319.457,0,0,1,59.277,57.715c25.185,32.144,46.688,75.329,47.594,116.593C763.65,545.042,743,570.339,696.672,606.357,641.857,634.242,640.447,634.792,640.447,634.792ZM672.715,493.3s-74.971-97.311-108.423-116.665S472.741,321.3,389.031,320.789c8.089-6.151,6.525-4.936,6.525-4.936l29.01-16.739a319.289,319.289,0,0,1,79.6-22.5c40.418-5.748,88.552-2.786,124.725,17.061,27.733,48.005,39.3,78.549,47.321,136.692C672.943,491.8,672.715,493.3,672.715,493.3Z"/>
<circle class="cls-2" cx="176" cy="176" r="60"/>
<rect id="Camera_Body" data-name="Camera Body" class="cls-3" x="38" y="38" width="1001" height="1001" rx="100" ry="100"/>
</clipPath>
Will display this
https://codepen.io/TVsVeryOwn/pen/yjwaoy
I'm trying to get something resembling this (I know my gradient is backwards):
< clipPath > only uses the fill of the shapes.
If you remove < rect id="Camera_Body" > part from your SVG code - you’ll see it’s working as you wanted without this rect element. The rect doesn’t have a fill - only a stroke - and the clipping doesn’t work on stroke.
This may help.
i"m using this awesome tutorial for creating circle progress bar.
but my problem is that i want to change the stroke-dasharray in the CSS:
fill: none;
stroke: #FF2A2A;
stroke-width: 9.9213;
stroke-miterlimit: 10;
stroke-dasharray: 1.4308, 1.4308;
I want it to animate it like in the tutorial but to look like this image:
Dashed border circle
Try the following changes to the tutorial you mentioned:
progress.component.css:
~~~~~~~~~~~~~~~~~~~~~~~
.progress__meter {
stroke: #4CAF50;
}
.progress__value {
stroke: white;
transition: all 100ms;
}
progres.component.html:
~~~~~~~~~~~~~~~~~~~~~~~
<div class="progress">
<svg class="progress__svg" width="120" height="120" viewBox="0 0 120 120">
<circle class="progress__meter" [style.strokeDasharray]="5" cx="60" cy="60" [attr.r]="radius" stroke-width="11" />
<circle class="progress__value" [style.strokeDasharray]="circumference" [style.strokeDashoffset]="1-dashoffset" cx="60" cy="60" [attr.r]="radius" stroke-width="12" />
</svg>
<div class="progress__value-text">{{value}}%</div>
</div>
progress.component.ts:
~~~~~~~~~~~~~~~~~~~~~~
private progress(value: number) {
const progress = value / 100;
this.dashoffset = this.circumference * (progress);
}
I have a svg where I am highlighting my path on hover. Here is my svg
<svg version="1.1" x="0px" y="0px" viewBox="0 0 2986 886" enable-background="new 0 0 2986 886">
<image display="block" overflow="visible" width="2986" height="886" xlink:href="/A-1.jpg">
</image>
<path fill="none" stroke="#000000" strokeWidth="0.25" stroke-miterlimit="10" points="2781.5,905 2986,905 2986,865.6
2842.7,634.6 2635.2,601.1 " id="1"></path>
....
</svg>
Here is my css:
svg path{
fill:none;
pointer-events:all;
}
svg path:hover {
fill: rgba(73,143,226,0.80);
border: 5px solid #31C6FF;
}
svg rect:hover {
fill: rgba(73,143,226,0.80);
border: 5px solid #31C6FF;
}
svg polygon:hover {
fill: rgba(73,143,226,0.80);
border: 5px solid #31C6FF;
}
When I hover, my path changes to the proper color, but I don't get a border. What am I misunderstanding?
For SVG, use the stroke property instead of border.
Edit: As the owner of the question points out in comments, stroke-opacity: 1 was needed as well as stroke and stroke-width.
I have a following html:
<div id="divVis2" class="divVis">
<svg width="1540" height="345">
<defs>
<marker id="normal" viewBox="0 -5 10 10" refX="15" refY="-1.5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M0,-5L10,0L0,5"></path>
</marker>
<marker id="anomaly" viewBox="0 -5 10 10" refX="15" refY="-1.5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M0,-5L10,0L0,5"></path>
</marker>
</defs>
<g>
<path class="anomaly" marker-end="url(#anomaly)" d="M908.3739002256449,176.0182689704716L661.9527686239043,249.64760217208658"></path>
<path class="normal" marker-end="url(#normal)" d="M660.4045373167714,246.37428873149702L879.5700343222044,98.59473202412175"></path>
<path class="normal" marker-end="url(#normal)" d="M878.0019325543491,95.25420149730667L631.216835426003,167.4248240636326"></path>
</g>
<g>
<g transform="translate(889.5195255254339,91.88595979689137)">
<circle class="normal" r="12"></circle>
<text x="0" y="4" class="normal">133</text>
</g>
<g transform="translate(619.6992424549181,170.7930657640479)">
<circle class="normal" r="12"></circle>
<text x="0" y="4" class="normal">134</text>
</g>
<g transform="translate(650.4550461135419,253.0830609587274)">
<circle class="anomaly" r="12"></circle>
<text x="0" y="4" class="normal">137</text>
</g>
<g transform="translate(919.8716227360072,172.5828101838308)">
<circle class="normal" r="12"></circle>
<text x="0" y="4" class="normal">136_1</text>
</g>
</g>
</svg>
</div>
Its corresponding css is:
#divVis2 path {
fill: none;
/* stroke: #666; */
stroke-width: 0.5px;
}
#divVis2 path.normal {
stroke: #808080;
}
#divVis2 path.anomaly {
stroke: red;
stroke-width: 1.5px;
}
/* for the marker */
#divVis2 #normal {
fill: black;
stroke-width: 0.5px;
}
#divVis2 #anomaly {
fill: red;
stroke-width: 1.5px;
}
#divVis2 circle.normal {
fill: #ccc;
stroke: #ffffff;
stroke-width: 0.5px;
}
#divVis2 circle.anomaly {
fill: #ff0000;
stroke: #ffffff;
stroke-width: 0.5px;
}
#divVis2 text.normal {
font: 7px sans-serif;
pointer-events: none;
fill: black;
text-anchor:middle;
}
#divVis2 text.label {
font: 9px sans-serif;
pointer-events: none;
fill: blue;
text-anchor:middle;
}
The corresponding output in browser is:
Why are the arrows not getting displayed at the end of each path? I am unable to find out the problem in css selectors.
Here is a jsfiddle: http://jsfiddle.net/onh7t53o/
#divVis2 path {
fill: none;
/* stroke: #666; */
stroke-width: 0.5px;
}
has a higher specificity for the markers than
#divVis2 #normal {
fill: black;
stroke-width: 0.5px;
}
so the marker paths are fill="none" and the stroke-width is so thin because the markers are small that you can't see it.
I had this problem in an angular app that was using a <base> tag. In the context of a rich web app like one built on Angular, where you need to set the <base> tag to make HTML5-style navigation work, it can get messy to try to fix that in a permanent way.
In my case, the app I was working on was showing a SVG-based interactive diagram builder that would change the app url as I selected elements therein.
What I did was to add a global event handler that would fix all url(#...) inline styles in any <path> element found in the page:
$rootScope.$on 'fixSVGReference', ->
$('path').each ->
$path = $ this
if (style = $path.attr 'style')?
$path.attr 'style', style.replace /url\([^)#]*#/g, "url(#{location.href}\#"
Then trigger this handler in key places, like when the app state changes (I'm using ui-router)
$rootScope.$on '$stateChangeSuccess', ->
$timeout (-> $rootScope.$emit 'fixSVGReference'), 5
As well as anywhere where I know there'd be new/updated paths like these. Here, the $timeout thing is to account for the fact that the DOM nodes really are changed asynchronously sometime after the $stateChangeSuccess event is triggered.