I have few issues with the way sketch app is generating donut chart.
This is how am building the donut chart in Sketch app
Please refer to screenshots to follow
The generated SVG doesn't represent what was drawn in Sketch Questions:
Generated code by Sketch (https://jsfiddle.net/BrightPixels/932w6j9d/)
<?xml version="1.0" encoding="UTF-8"?>
<svg width="226px" height="226px" viewBox="0 0 226 226" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 45.2 (43514) - http://www.bohemiancoding.com/sketch -->
<title>donut-chart</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="iPad" transform="translate(-236.000000, -213.000000)" stroke-width="25">
<g id="donut-chart" transform="translate(249.000000, 226.000000)">
<circle id="base" stroke="#D8D8D8" cx="100" cy="100" r="100"></circle>
<circle id="segment1" stroke="#FFD900" stroke-dasharray="314,314" cx="100" cy="100" r="100"></circle>
<circle id="segment2" stroke="#64B445" stroke-dasharray="157,471" transform="translate(100.000000, 100.000000) rotate(90.000000) translate(-100.000000, -100.000000) " cx="100" cy="100" r="100"></circle>
<circle id="segment3" stroke="#004FB6" stroke-dasharray="157,471" transform="translate(100.000000, 100.000000) rotate(180.000000) translate(-100.000000, -100.000000) " cx="100" cy="100" r="100"></circle>
</g>
</g>
</g>
</svg>
There are two ways that I would suggest building this, and neither rely on rotate transforms. Transforms (especially when exported from design tools alongside other attributes like stroke-dasharray or masks) can cause issues.
If this is intended to be a static graphic that doesn't need to change, you could simply take this approach in Sketch:
• Create 3 identical circle layers, with yellow, green, and blue borders.
• For each circle, use the Scissors tool to remove line segments from the circle.* For example, for the blue layer, you'd use the Scissors tool to remove all but one of its line segments. I also wrote an article about how to use the Scissors tool.
• Note that this approach doesn't use rotate transforms. It should export easily and identically from Sketch to SVG.
* A line segment is the path in between any two vector points, so if you wanted part of the circle to end at an arbitrary point (ex: 4 o'clock) where there isn't already a vector point you can just go into Edit mode and click along the path to add a vector point there.
If this is intended to be a dynamic graphic that changes based on real data (like a pie chart), stroke dashes are a good idea but I would suggest doing some of the work directly in the SVG:
• Start in Sketch by creating that same circle layer (only one).
• This way of using stroke dashes relies heavily on 1. the start point of the circle, and 2. the path direction of the circle. We can figure those out in Sketch by entering Edit mode on the circle (return
key); the selected vector point is the start point, and hitting the tab
key will cycle through the other points moving in the direction of the path. Based on Sketch's defaults for a circle, we'll need to make the following adjustments to get a circle that starts at 12 o'clock and moves clockwise:
• Rotate the circle 180°, then click Flatten in the toolbar (or in the menu bar, via Layer > Combine > Flatten). In addition to removing the rotate transform, this turns it into a custom path instead of a standard circle. It will export to SVG as a <path>
element instead of a <circle>
.
• The path direction is currently counter-clockwise, so if you want it to be clockwise you should also go to Layer > Path > Reverse Order to switch the path direction. Now we have exactly the circle path that we want—no need for rotations in the SVG.
• After exporting to SVG, I suggest copying the code into a CodePen, as I've done here in this demo. To start, move the <path>
element into the <defs>
area so that you can easily clone it for each of the colored segments.
• Create 3 <use>
elements that reference the <path>
, each with their own stroke colors. See my CodePen link if you aren't familiar with how to do this.
• Add a stroke-dasharray
attribute to each of the <use>
elements. They should have 2 values: 1. the length of the segment you want to create, and 2. the length of the gap between dashes—which should be equal to or greater than the length of the path itself. In this case the path length is about 628, which can be calculated using the little bit of Javascript I included in that CodePen (open up the console to see the resulting number). In this example, the green and blue circles take up 1/4 of the circle path, so they should have a stroke-dasharray
of 157, 628
.
• Because these dashes all start at the beginning of the path, we need to offset them. We don't need to use a rotate transform for this—instead I suggest using stroke-dashoffset
which was created for this exact reason. The offset takes one number value: the distance it moves the dashes in the opposite direction as the path. That means we need to use negative values to move in the same direction as the path. To offset the green segment by half of the circle, that attribute should be stroke-dashoffset="-314"
.
• The nice thing about this approach is that you could easily use Javascript or CSS calc() to easily set the stroke-dasharray
and stroke-dashoffset
values for these colorful segments, and update them based on new data.
Woohoo—dynamic charts!