Reputation: 1053
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
ctx.lineWidth = 2;
ctx.font = '14px verdana';
var PI2 = Math.PI * 2;
var myColor = ["Green", "Red", "Blue"];
var myData = [30, 15, 38, 22, 30, 20, 10];
var cx = 150;
var cy = 150;
var radius = 100;
ctx.globalAlpha = 0.50;
pieChart(myData, myColor);
ctx.globalAlpha = 1.00;
function pieChart(data, colors) {
// calc data total
var total = 0;
for (var i = 0; i < data.length; i++) {
total += data[i];
}
// calc sweep angles for each piece of pie
var sweeps = []
for (var i = 0; i < data.length; i++) {
sweeps.push(data[i] / total * PI2);
}
// draw outer pie
var accumAngle = 0;
for (var i = 0; i < sweeps.length; i++) {
var f = randomColor();
drawWedge(radius, accumAngle, accumAngle + sweeps[i], f, data[i]);
accumAngle += sweeps[i];
}
}
function drawWedge(radius, startAngle, endAngle, fill, label) {
// draw the wedge
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.arc(cx, cy, radius, startAngle, endAngle, false);
ctx.closePath();
ctx.fillStyle = fill;
ctx.strokeStyle = 'white';
ctx.fill();
ctx.stroke();
}
function randomColor() {
return ('#' + (Math.floor(Math.random() * 0x1000000) +
0x1000000).toString(16).substr(1));
}
<canvas id="canvas" width=512 height=512></canvas>
I have a simply question - is there any option to add a tooltip on mouseover event on canvas pie arc? Can anyone help me how could i do that. I am able to draw a pie chart using canvas please fine the below snippet:
Upvotes: 0
Views: 1356
Reputation: 54089
At the most basic level you can use the canvas.title property to set the tooltip. Just get the mouse move events and record the mouse position. Then when you detect that the mouse has changed position, check which slice the mouse is over, if any and set the tooltip to match.
Note that the browsers tooltip is a little slow to respond to changes.
You could also draw the chart every frame of the render loop and highlight the parts of the pie the mouse is over and create a more responsive tooltip than the browser default which can be a little slow to respond at times.
The example below is just your code with the modification needed to get the basic tooltip.
Note that I keep the mouse event listener and the function that changes the tooltip separate, this is because on some systems the mouse can have a very high sample rate (my current gaming mouse can fire 700+ times a second) and doing too much in the mousemove event can cause laggy response to user input.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
ctx.lineWidth = 2;
ctx.font = '14px verdana';
var PI2 = Math.PI * 2;
var myColor = ["Green", "Red", "Blue"];
var myData = [30, 15, 38, 22, 30, 20, 10];
var cx = 150;
var cy = 150;
var radius = 100;
var mouse = {x :0,y:0,oldx : 0,oldy:0};
ctx.globalAlpha = 0.50;
pieChart(myData, myColor);
ctx.globalAlpha = 1.00;
function pieChart(data, colors) {
// calc data total
var total = 0;
for (var i = 0; i < data.length; i++) {
total += data[i];
}
// calc sweep angles for each piece of pie
var sweeps = []
for (var i = 0; i < data.length; i++) {
sweeps.push(data[i] / total * PI2);
data[i] = {
value : data[i],
angle : data[i] / total * PI2,
text : "Data is "+((data[i] / total) * 100).toFixed(0) + "%",
}
}
// draw outer pie
var accumAngle = 0;
for (var i = 0; i < sweeps.length; i++) {
var f = randomColor();
drawWedge(radius, accumAngle, accumAngle + sweeps[i], f, data[i].value);
accumAngle += sweeps[i];
}
}
function drawWedge(radius, startAngle, endAngle, fill, label) {
// draw the wedge
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.arc(cx, cy, radius, startAngle, endAngle, false);
ctx.closePath();
ctx.fillStyle = fill;
ctx.strokeStyle = 'white';
ctx.fill();
ctx.stroke();
}
function randomColor() {
return ('#' + (Math.floor(Math.random() * 0x1000000) +
0x1000000).toString(16).substr(1));
}
canvas.addEventListener("mousemove",function(event){
mouse.x = event.clientX;
mouse.y = event.clientY;
})
function update(){
// only on change in mouse position
if(mouse.x !== mouse.oldx || mouse.y !== mouse.oldy){
var x = mouse.oldx = mouse.x;
var y = mouse.oldy = mouse.y;
x -= cx; // vector from pie center
y -= cy;
var newText = "My pie chart. Mouse over slices for more info.";
var dist = Math.sqrt(x * x + y * y); // get distance from center
if(dist < radius){
var ang = Math.atan2(y,x); // get angle note y is first
ang += Math.PI * 2; // rotate 360 as atan2 starts at -Pi
ang %= Math.PI * 2; // normalize to range 0 to 2Pi
var i = 0;
var tAng = 0
while(i < myData.length-1){
if(ang < tAng + myData[i].angle){
break;
}
tAng += myData[i].angle;
i += 1;
}
newText = myData[i].text;
}
canvas.title = newText;
}
requestAnimationFrame(update);
}
update();
<canvas id="canvas" width=512 height=512></canvas>
Upvotes: 2