How to Build this Rounded Two Tone Donut Chart?

All we need is an easy explanation of the problem, so here it is.

I’m trying to make a donut chart that looks like one below

Donut Chart

I’ll be using angularJS, SVG and D3.js

I’ve no clue how to get those rounded ends, Please help. Thanks.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Simple answer: you use masks.

We use a mask to draw the inner portion of the bezel. And a mask to cut the hole in the middle.

The hole mask isn’t really necessary. You could form the donut with thick lines. But it seemed easier to me to draw circular sectors, then make the hole.

Here it is in SVG form. I’ll leave the conversion to D3 to you.

<svg width="600" height="600">
    <defs>
        <!-- masks out the area outside and inside the inner bevel region -->
        <mask id="innerbevel">
            <rect width="100%" height="100%" fill="black"/>
            <circle cx="0" cy="0" r="235" fill="white"/>
        </mask>
        <!-- cuts hole in centre of graph -->
        <mask id="centrehole">
            <rect x="-100%" y="-100%" width="200%" height="200%" fill="white"/>
            <circle cx="0" cy="0" r="195" fill="black"/>
        </mask>
    </defs>

    <!-- Graph is drawn centred at (0,0). The transform moves it into middle of SVG. -->
    <!-- The mask forms the hole in the centre. -->
    <g transform="translate(300,300)" mask="url(#centrehole)">
        <!-- outer bevel -->
        <g>
            <!-- light blue segment -->
            <path d="M0 0 0 -275 A 275 275 0 0 1 0 275" fill="#89e4d2"/>
            <!-- red segment -->
            <path d="M0 0 0 275 A 275 275 0 0 1 -275 0" fill="#f394a2"/>
            <!-- blue segment -->
            <path d="M0 0 -275 0 A 275 275 0 0 1 0 -275" fill="#a3a4ff"/>

            <!-- light blue rounded end -->
            <circle cx="0" cy="235" r="40" fill="#89e4d2"/>
            <!-- red rounded end -->
            <circle cx="-235" cy="0" r="40" fill="#f394a2"/>
            <!-- blue rounded end -->
            <circle cx="0" cy="-235" r="40" fill="#a3a4ff"/>
        </g>
        <!-- inner bevel - same as above but with different colours and is masked -->
        <g mask="url(#innerbevel)">
            <!-- light blue segment -->
            <path d="M0 0 0 -275 A 275 275 0 0 1 0 275" fill="#5bc8b7"/>
            <!-- red segment -->
            <path d="M0 0 0 275 A 275 275 0 0 1 -275 0" fill="#ef6974"/>
            <!-- blue segment -->
            <path d="M0 0 -275 0 A 275 275 0 0 1 0 -275" fill="#6b5dff"/>

            <!-- light blue rounded end -->
            <circle cx="0" cy="235" r="40" fill="#5bc8b7"/>
            <!-- red rounded end -->
            <circle cx="-235" cy="0" r="40" fill="#ef6974"/>
            <!-- blue rounded end -->
            <circle cx="0" cy="-235" r="40" fill="#6b5dff"/>
        </g>
    </g>

</svg>

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply