menu

Usage of SVG stroke dasharray

Amit

TreeImage
TreeImage

I am still new to SVG and its quite exciting whenever I come to know more about it. Recently, I did an experiment with stroke-dasharray an SVG presentational attribute. It amazed me when I came to know how tricky and mysterious it can be.

Let me explain my requirement where I need a multi color donut chart, as shown in the below image:

Hollow Pie chart representation

Source: https://commons.wikimedia.org/wiki/File:Vega-piechart.png

From Lea’s article, I came to know how to create a basic donut chart using SVG’s stroke-dasharray. So I decided to create a multi-coloured donut chart without using any library. I just need to build my own component based on Lea’s idea. To summarize lea’s article, it all comes down to coloring the required potion of circle's circumference with specified color

Screen-Shot-2018-02-02-at-6.32.47-PM.png

So, in stroke-dasharray, we will have two values, first will be the circumference in required percentage and the next will be the circumference itself. i.e

Screen-Shot-2018-02-02-at-6.36.08-PM.png

Now, if I have the following circle:
<svg>
<circle cx="50" cy="50" r="50"></circle>
</svg>

As the radius for circle is 50 and assumed applied percentage is 60%, the stroke-dasharray would look like:

Screen-Shot-2018-02-02-at-6.36.17-PM.png

As stroke-dasharray is a presentational attribute, we can apply the above using css:

circle {
stroke-dasharray: calc(2 * 22 / 7 * 50), calc(2 * 22 / 7 * 50 * 60 / 100);
stroke-width: 10;
}

The circumference formula in above calculation needn’t to be executed on runtime. So, I will switch over to SCSS to precompile the calculation and make the code more readable (this step is not redundant but still who doesn’t love SCSS ? ).

circle {
$pi: 22/7;
$radius: 50;
$circumference: 2 * $pi * $radius;
stroke-dasharray: calc(#{$circumference} * 60 / 100), #{$circumference};
stroke-width: 10;
}

Again since the percentage value is dynamic, it is better to handle the stroke-dasharray value using JavaScript (even the circumference calculations). But if you are fine with CSS Custom Variables then you can do as follows:

:root {
--percent: 0; // default value
}

circle {
$pi: 22 / 7;
$radius: 50;
$circumference: 2 * $pi * $radius;
stroke-dasharray: calc(#{$circumference} * var(--percent), #{$circumference};
stroke-width: 10;
}

The above explanation just covers the fundamentals to create a single pie in donut chart. Now to create another pie inside the donut chart, we need to create another circle inside SVG.

<svg>
<circle class="pie-one" cx="50" cy="50" r="50"></circle>
<circle class="pie-two" cx="50" cy="50" r="50"></circle>
</svg>

If we say the first pie holds 60% and the second 20%, then second pie would start from on top of the first pie's stroke when it is rendered because the circle positions are same, hence the stroke color will be overlapping one on another. To make the second pie visible, we need to rotate it by 60% (i.e first pie’s percentage). i.e

Screen-Shot-2018-02-02-at-6.36.32-PM.png

Well if there is another pie, we need to rotate it by first pie's percentage + second pie's percentage. Since all pie diagrams start with a 90o off, it is better to rotate all these circles by -90o or 270o maybe through a parent element i.e a group tag.

<svg>
<g class="circles">
<circle class="pie-one" cx="50" cy="50" r="50"></circle>
<circle class="pie-two" cx="50" cy="50" r="50"></circle>
<circle class="pie-three" cx="50" cy="50" r="50"></circle>
</g>
</svg>

.circles {
transform: rotate(-90deg);
}

As in the real scenario, the circles could be dynamic, it is better to generate the circles through JavaScript and pass the percentage values through an object. I got my donut chart by following the above steps, hope it will be helpful to you as well.

See the Pen Hollow pie chart by venkateshwar (@Mr_Green) on CodePen.

butterfly
Let'sTalk
butterfly
Thanks for the submission.