I’m trying to accomplish this… in this example the green stroke is filled when the people selected (1), and the gray ones are the total of people (6)
other example is green stroke is filled (3) and total (6)
what I accomplished by now, it doesn’t fill correctly,
const [personQuantity, setPersonQuantity] = useState(2)
const [payingFor, setPayingFor] = useState(1)
useEffect(() => {
let amountPerPerson = subtotal / personQuantity
let perPerson = amountPerPerson * payingFor
setPerPerson(perPerson)
if (personQuantity >= payingFor && personQuantity > 2) {
setActivate(true)
} else {
setActivate(false)
}
}, [personQuantity, payingFor])
const fillPercentage = (payingFor / personQuantity) * 100
return (
<>
<div className="h-20 w-20 ">
<svg className="circular-chart " viewBox="0 0 36 36">
<path
fill="none"
strokeWidth="4"
strokeDasharray={`${fillPercentage + 1},1`}
className="circle-bg bg-DARK_1 stroke-2 stroke-white"
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
/>
<path
strokeWidth="4"
strokeLinecap="round"
fill="none"
className="circle stroke-LIGHT_GREEN_1 transition-opacity delay-150 ease-in-out"
strokeDasharray={`${fillPercentage}, 100`}
d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
/>
</svg>
</div>
2
Answers
as stated by enxaneta, you use path of 100 percent, so you should make the math so that the white draws the person’s number separated by a gap percent space and the green fills the number of slots including intermediate spaces.
So assuming subtotal is the total number of persons and payingFor is the number of persons that should be green, we have :
so for white :
then for green :
Please note that it will be incorrect with more than 100 persons because these would imply more than 100 gaps of 1 percent and negative space between them, so you should probably put the gapSize to 0 when subtotal is more than ~40 (esthetic value)
As a second note, while using a path to approximate a circle do work, I recommend using
<circle cx="18" cy="18" r="15.9155" pathlength=100>
and in both case you will need to rotate the figure by -90deg to achieve the vertical origin of the drawingtransform: rotate(-90deg)
I did a demo on this codepen (with fixed values)
Authoring react in StackOverflow is painful so I wrote a response in pure HTML / CSS, but hopefully this can help you see how this would work.
Except for a bit of math, the initial issue is to be able to calculate the total length that you need to base your % calculations on. In this case I’m using a
<circle>
so it’s trivial (2 * π * r), but if you absolutely need to use a<path>
there is a native JS methodgetTotalLength
(https://developer.mozilla.org/en-US/docs/Web/API/SVGGeometryElement/getTotalLength) that can compute it for you.Then we use
stroke-dasharray
that has the syntax "length visible, length hidden".For the segmented circle, the length hidden (
--gap
) is trivial and up to you. The length visible is simplytotal / segments - gap
. For example, in circle with 3 segments, there will also be 3 gaps, so no hidden trick here.For the progress circle, the visible length would be
total / segments * current
(and hidden length would be the rest). However we need to adjust for the gaps if you want it to stop at the same points that the segmented circle stops. Basically-gap
for the visible length, and+gap
for the hidden length.And just for fun, here’s a full example with buttons so you can test the accuracy of this solution: