3

I'm trying to learn canvas by implementing a pie chart. I've managed to parse my data, draw the slices, and calculate the center of each arc, as noted by the black circles. But now I'm trying to draw one of the slices as though it had been "slid out". Not animate it (yet), just simply draw the slice as though it had been slid out.

I thought the easiest way would be to first calculate the point at which the new corner of the slice should be (free-hand drawn with the red X), translate there, draw my slice, then translate the origin back. I thought I could calculate this easily, since I know the center of the pie chart, and the point of the center of the arc (connected with a free-hand black line on the beige slice). But after asking this question, it seems this will involve solving a system of equations, one of which is second order. That's easy with a pen and paper, dauntingly hard in JavaScript.

Is there a simpler approach? Should I take a step back and realize that doing this is really the same as doing XYZ?

I know I haven't provided any code, but I'm just looking for ideas / pseudocode. (jQuery is tagged in the off chance there's a plugin will somehow help in this endeavor)

enter image description here

Community
  • 1
  • 1
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393

2 Answers2

3

Merely translating an element on a canvas is very easy and there shouldn't be any tricky equations here. In the most basic sense it is:

ctx.save();
ctx.translate(x, y);
// Draw the things you want offset by x, y
ctx.restore();

Here's a rudimentary example of a square pie and the same pie with one of the four "slices" translated:

http://jsfiddle.net/XqwY2/

To make the pie piece "slide out" the only thing you need to calculate is how far you want it to be. In my simple example the blue block is slid out 10, -10.

If you are wondering merely how to get the X and Y you want in the first place, well, that's not quite a javascript/canvas question. For points on a line given a distance this question: Finding points on a line with a given distance seems the most clear

Edit, here you are (from comments):

  // Center point of pie
  var x1 = 100;
  var y1 = 100;

  // End of pie slice (your black dot)
  var x2 = 200;
  var y2 = 0;

  // The distance you want
  var distance = 3;

  var vx = x2 - x1; // x vector
  var vy = y2 - y1; // y vector
  var mag = Math.sqrt(vx*vx + vy*vy); // length
  vx = mag/vx;
  vy = mag/vy;

  // The red X location that you want:
  var px = x1 + vx * ( distance);
  var py = y1 + vy * ( distance);

This would give you a px,py of (104.24, 95.76) for my made-up inputs.

Community
  • 1
  • 1
Simon Sarris
  • 62,212
  • 13
  • 141
  • 171
  • Yes, I am indeed wondering how to get the `x` and `y`. It's a math question, but anyone who's done something similar in canvas will likely have seen this – Adam Rackis Jan 11 '12 at 20:17
  • There are a lot of questions already dealing with that, ie: http://stackoverflow.com/questions/1800138/given-a-start-and-end-point-and-a-distance-calculate-a-point-along-a-line but if you need a code sample I could make one – Simon Sarris Jan 11 '12 at 20:21
  • I don't need a code sample, just an algorithm - which I think this question will answer – Adam Rackis Jan 11 '12 at 20:22
  • Thanks for your help. I couldn't quite get this to work, but I threw you an extra +1 for your time -- 9 more to go before you hit 10K :) – Adam Rackis Jan 11 '12 at 21:03
3

Getting the x and y of the translation is easy enough.

// cx and cy are the coordinates of the centre of your pie
// px and py are the coordinates of the black circle on your diagram
// off is the amount (range 0-1) by which to offset the arc
//      adjust off as needed.
// rx and ry will be the amount to translate by

var dx = px-cx, dy = py-cy,
    angle = Math.atan2(dy,dx),
    dist = Math.sqrt(dx*dx+dy*dy);
rx = Math.cos(angle)*off*dist;
ry = Math.sin(angle)*off*dist;

Plug that into the code Simon Sarris gave you and you're done. I'd suggest an off value of 0.25.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • I assume an `off` of 0.5 would put be exactly halfway between the center of the pie and the black dot? – Adam Rackis Jan 11 '12 at 20:27
  • Is there a typo in your code? I'm getting tiny, tiny values for rx and ry -> like 0.01 Here are the exact values: http://jsfiddle.net/tnE87/ – Adam Rackis Jan 11 '12 at 20:43
  • `rx += cx;` and the same for ry, and it looks like this is what I need – Adam Rackis Jan 11 '12 at 20:55
  • rx and ry are the amount to translate by, so to get the new centre adding cx and cy is correct. – Niet the Dark Absol Jan 11 '12 at 20:57
  • Yes, sorry, you had that in your comment. Dude, thank you SO much for your help. I see you design games, which I guess explains how you know your trig so well :) – Adam Rackis Jan 11 '12 at 21:01
  • Trig is VERY important in game design, yup. It's amazing how often I use them, to be honest. Anything remotely wave-related? `sin` and `cos` all the way. That said, I'm struggling to learn 3D-trig... which I need to do if I want to start making 3D games... – Niet the Dark Absol Jan 11 '12 at 21:02