I am trying to create Polar Area Chart using canvas here :
http://jsfiddle.net/wm7pwL2w/2/
Code:
var myColor = ["#ff0", "#00f", "#002", "#003", "#004"];
var myData = [10, 30, 20, 60, 40];
var myRadius = [120, 80, 40, 70, 40];
function getTotal() {
var myTotal = 0;
for (var j = 0; j < myData.length; j++) {
myTotal += (typeof myData[j] == 'number') ? myData[j] : 0;
}
return myTotal;
}
function plotData() {
var canvas;
var ctx;
var lastend = 0;
var myTotal = getTotal();
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < myData.length; i++) {
ctx.fillStyle = myColor[i];
ctx.beginPath();
ctx.moveTo(200, 150);
ctx.arc(200, 150, myRadius[i], lastend, lastend + (Math.PI * 2 * (myData[i] / myTotal)), false);
console.log(myRadius[i]);
ctx.lineTo(200, 150);
ctx.fill();
lastend += Math.PI * 2 * (myData[i] / myTotal);
}
}
plotData();
Update: To clear things out this is what I want to implement :
<>
This style with this :
(This is a simple pie chart) I am not able to implement the second part(exploding the slices) with my current implementation.
For this I would use an object model as well as keeping a parent-child relationship between the chart and the slices. This way I can work with just the chart model having it render all the children, and I could expand the slice object to do more powerful stuff. I did not support text in this example but this should be easy to add from here.
Ok, first lets built a parent object - the chart itself:
Its pretty basic and it does not yet contain all the functionality we need. We could build the function directly into this object but in case we use several instances of the Chart object it would be smarter to share that memory-space between each instance, so we're gonna use the prototype model instead.
Lets first make a function to add a
Slice
object:Here we see it creates a
Slice
object (see below), then adds it to the slice array, updates the total sum and returns itself so we can chain it.The
Slice
object (child) is fairly simple here, but by keeping it as an object rather than a literal object or an array we can expand it later with powerful functionality if we want with little to no modification of parent (you could have parent call a render vector on each slice itself to render itself instead of doing it in parent). Besides from that, objects compile well within modern browsers:That's about it. We support an offset value (from center) which defaults to 0 if not given.
All we need to do now is to have a function that iterates over each slice and render them to canvas at offset, angle, color and so forth.
The magic happens here:
That´s it. The order of the transforms is important:
Now we can create the charts and the slices this way:
For each add the data value is accumulated to a total value. This total value then becomes the value used to find how large the angle should be for each slice:
Here we first get a percentage of total:
this percentage is used of the full circle (2 x PI):
So no matter how many slices we add we will dynamically adjust their angles relative to each other and the total.
Now, simply call:
to render it all.
To adjust, and even animate the offsets, we can create utility functions such as in the live code below, or simply set an offset directly for each slice in the array:
Put it in a loop with
requestAnimationFrame
and you can animate it with various offsets and all you need to worry about is 1-dimensional values (anyone care for a sinus wave explosion?).How you define the parameters and methods for the objects is up to you, but with this you should be able to expand and refine as needed.
Hope this helps!
You are not supposed to change the values of the Radius 'myRadius', it must be constant (simple math).
Check http://jsfiddle.net/sameersemna/xhpot31v/