Maffoo

I have arms and legs and I sometimes use them to type things. Follow me on pinstagram.

Simple CSS3 animatable donut/doughnut pie charts

Simple CSS3 animatable donut/doughnut pie charts

Recently I had to create an animating doughnut chart for a client, which would work well across devices, show percentages and take the least amount of time to implement. It's something that comes up 1,000 times when searching the interwebs, but they all seem to have some major flaw or are overly complicated.

The closest I got to finding one in the wild was this pen: http://codepen.io/joeyclouvel/pen/rDchL which, although not terrible, has a fair bit to be desired.

See the Pen Customisable Animated Donut Chart by Joey Clouvel (@joeyclouvel) on CodePen.

One of the main issues is that it uses window.setInterval(), which is pretty oldskool and doesn't always play nicely— it should be using window.requestAnimationFrame().

Another issue is that it animates an SVG path's d="" attribute directly, which is fine on some browsers but not on others (it basically destroys Safari). After the Safari-death scenario, I decided I would try and make it work with CSS transitions instead.

The magic in this new version comes from the SVG properties stroke-dasharray and stroke-dashoffset, which we'll abuse beyond their intended purpose, as well as getAnimationFrame and getComputedStyle. Everything else is just pretty bog-standard CSS/JS and is definitely not intended to be seen as the most beautifully written code :wink:

The property stroke-dasharray turns a stroke into an array of dashes (go figure!), with its value denoting the width of each dash. The property stroke-dashoffset then says how many pixels we'll offset the dashes by.

If we set the stroke-dasharray to the length of our path and modify the offset, we can quite easily create percentage width lines. When the offset is at 0, it's 100% wide. When the offset is at the width of the path, the line has been pushed out of the clipping area and appears invisible. If we now reverse animate between these two values, we get a line that moves from 0-100%.

See the Pen SVG line stroke-dashoffset animation by Matt Fletcher (@MaffooBristol) on CodePen.

This may not seem that impressive, but it becomes a lot cooler when we realise that we can run this on curves, circles and any other shape (as long as we can programatically work out the line's length, more about that in a second). See below the same code but on a circle rather than a straight path:

See the Pen SVG line stroke-dashoffset animation on circle by Matt Fletcher (@MaffooBristol) on CodePen.

This has worked pretty well, but has one flaw: the animation is meant to ease in and out, so it should slow to a stop when it reaches itself at the end of the circle. However, the stroke length and offset are waaaay too long for this shape- unroll the 100px radius circle and it's no longer 1000px wide, in fact it's 628.318530718px. That nice neat number is of course from primary school maths: c=2πr, or circumference = radius * pi * 2

Let's try it again but with both values at six-hundred-and-whatever:

See the Pen SVG line stroke-dashoffset animation on circle (adjusted) by Matt Fletcher (@MaffooBristol) on CodePen.

Much nicer! The next thing to do is make it so our doughnuts can animate between percentage values. To do this, we will have to use a simple formula to convert the % into the stroke-dashoffset value: offset = circumference - (circumference * percent / 100)

The following pen takes this formula and uses it to assign the new dashoffset. I have also added a transform: rotate(90deg); and transform-origin: 50%; to make sure the rotation starts from the top.

See the Pen SVG line stroke-dashoffset animation on circle (using percentages) by Matt Fletcher (@MaffooBristol) on CodePen.

Then we add in the static number with a bit more styling:

See the Pen SVG line stroke-dashoffset animation on circle (with static number) by Matt Fletcher (@MaffooBristol) on CodePen.

Finally, we want to actually update the text value based on the current position of the doughnut. The best way to do this is actually take the computed value of the animating SVG stroke, put it into the reverse of the above percent->offset calculation and then update it based on that. To make sure this runs smoothly, we will run this code in each requestAnimationFrame.

See the Pen SVG line stroke-dashoffset animation on circle (with working number) by Matt Fletcher (@MaffooBristol) on CodePen.

I'll probably update this blog post at some point, so apologies if it's a bit messy.

Lots of love,
Maff
xxx

I really should do something with this blog

I really should do something with this blog

I've had ideas for posts to write, but then I just do about 100 words and get bored.

What shall I write about, silent internet crowd?

Perhaps my experiences with trying to help out in the socket.io issues queue? Nah, I think you'd all need to watch Schindler's List to cheer yourselves up after reading that.

Stay chooned.

Always,
Maff
xxx

Eeyah, world.

Eeyah, world.

S'later, Rackspace.

So, after owning a Rackspace server for several years and never really seeing the benefit of doing so, I've finally transitioned 100% over to Digital Ocean, who are far, far cheaper and seem to provide the exact same service.

Every other server I've fired up since this one has been a Digital Ocean droplet and, other than the ballache of having to go through my old Fedora (shudder) box and work out what needs keeping and what needs chucking, it made sense to move my maffoo.co.uk domain over too. Also, if I have to watch another one of their fucking cringe-worthy Christmas card videos, I think I may just end up giving myself an ad-hoc vasectomy with my bare fingers.

Ghost tings.

I've very quickly fired up a Ghost blog (and it really was quick!) rather than bugger about with making my own Node-based site/blog: something I was playing about with a while ago but, without infinite time and resources (and interest), decided it would make sense just to go for something easy.

Theme Lover (1958)

Currently I'm running a slightly modified version of Ascent, but I will do a proper theme some time soon because this one's a bit pants...

Official conclusion.

Stay tuned for incredible blog posts that will literally blow your anuses inside-out. Just wait.

Love, Maff.
xxx