SVG Donut Charts 2

Here we use some data from my Knowledge Base database of books to display the top 5 subject headings as a donut chart.

Typically the data would be pulled from a database, which would then make this script dynamic (I don't have to update it every time the DB is changed).

The data would then be mangled into shape to be displayed as SVG. However in this case I hard-coded the data.

On the previous page we used JavaScript functions to draw the image. Here the following data is used:

Total # of resources (Books & Articles): 352 (from my Knowledge Base library).

The 5 keywords, number, color used:

  1. Mathematics 116 purple
  2. Perl 109 red
  3. MySQL 51 gray
  4. Physics 38 green
  5. Reference 38 orange

Note that these keywords and numbers represent only a small fraction of the total number of keywords, and their numbers. There are 273 unique keywords and 812 resources. This is important when we do the math later.

If you view the source code (recommended) you may notice a few new things. SVG text can be mangled, almost like CSS. In this example I use font-family="Chalkboard SE" and also change the size font-size="20". In SVG the font size is assumed to be in pixels, so no unit type is needed.

The arrays holding keywords, colors, and numbers are sorted by number in descending order. The arrays are in the same order so we can use an index in a loop, thus ensuring everything matches up.

Doing JavaScript inside SVG can be a bit tricky, especially any printing, which we need to do.

Since there are a lot of variables used, as in a loop, we need to print them very carefully. Quoting in JavaScript is a bit of a bear.

For example, to print the SVG to create the small circles and text in the middle, for each keyword, had to be done like this, in a loop:

StartAngle=0; for (ndx in Qty) { thisQty=Qty[ndx]; var thisAngle = (thisQty / TotalQty) * 360; thisColor=Colors[ndx]; EndAngle=StartAngle+thisAngle; Sprint('<circle r='+r+' cx='+cx+' cy='+cy+ ' fill='+Colors[ndx]+'>'); Sprint('<text fill="black" font-size="20" font-family="Chalkboard SE" x='+X+' y='+Y+'>'+Keys[ndx]+' '+Qty[ndx]+''); cy+=35; Y+=35; document.getElementById(thisColor).setAttribute("d",describeArc(CX,CY,R,StartAngle,EndAngle)); StartAngle=EndAngle; EndAngle+=StartAngle; }

The observant viewer will note a JavaScript command 'Sprint', which is actually a JavaScript function I made. It replaces 'document.write' in a print statement. I'm a programmer (so lazy) and hated typing that out all the time. It's also in the 'svgMath2.js' script.

/* JS print short-cut */ var Sprint = function(s) { document.write(s); }

As mentioned, a lot of variables are used: ndx, thisQty, TotalQty, thisColor, r, cx, cy, Colors[ndx], X, Y, Qty[ndx], CX, CY, R, thisAngle, StartAngle, EndAngle.

All JavaScript identifiers are case sensitive.
'ThisVariable' is NOT the same as 'thisVariable'

Wherever a variable is used, it can't be printed directly, but must be quoted.

The string concatenation symbol in JavaScript is the plus sign + , so the print statement has to be built using that. Sometimes a quantity has to be double-quoted " in HTML. Now you have single and double quotes involved. Oh, and of course they have to match.

My advice ... Be patient and VERY careful. It will be worth it.

A final note on how this works. Building up the donut this way, the first arc begins at 0° (12:00). But where does it end? Ahh, for that we need thisAngle, StartAngle and EndAngle.

First we need thisAngle which is determined by the current keyword quantity, divided by the total quantity, multiplied by 360. (convert the keyword quantity into a degree value)

EndAngle is determined by adding thisAngle to StartAngle.

Finally we set the next StartAngle to the current EndAngle, and add StartAngle to the current EndAngle.

Confused yet?