简体   繁体   中英

Update pie slice size in Raphael pie chart

I'm working on making a pie chart that shows results over time. As such it needs to animate between states to show how different slices change. I've figured out how to change all the slices en masse (using this example as a starting point), but I would like to be able to select and manage a particular slice (or sector as Raphael calls it) at a time. Has anyone figured out how to do that? I've found that if var pie is my pie chart, then I can get a particular slice with:

var pie = r.g.piechart(200, 200, 150, dataArray);
slice = pie.series[0];

But when I attempt to change the slice with say, an animation (specifically to change its size), that fails (segment is not the right way?):

slice.animate({segment: [200, 200, 0, 100]}, 800);

Any insight into manipulating individual slices would be very helpful.

I realized with much embarrassment that the segment attribute was a custom attribute created and used in an example I found to update the path of a pie slice, and therefore its size. It looks like this:

  var r = Raphael("holder");
  r.customAttributes.segment = function (x, y, r, a1, a2) {
      var flag = (a2 - a1) > 180,
          clr = (a2 - a1) / 360;
      a1 = (a1 % 360) * Math.PI / 180;
      a2 = (a2 % 360) * Math.PI / 180;
      return {
          path: [["M", x, y], ["l", r * Math.cos(a1), r * Math.sin(a1)], ["A", r, r, 0, +flag, 1, x + r * Math.cos(a2), y + r * Math.sin(a2)], ["z"]],
          fill: "hsb(" + clr + ", .75, .8)"
      };
  };

Here's what this might look like in context: I have three values [10, 20, 15] that total to 45. Assuming a circle with a width and height of 250, I can populate the circle with slices using the segment custom attribute like this (assuming I have a div on my page with the id of holder):

var r = Raphael("holder");
r.customAttributes.segment = function (x, y, r, a1, a2) {
    var flag = (a2 - a1) > 180,
        clr = (a2 - a1) / 360;
    a1 = (a1 % 360) * Math.PI / 180;
    a2 = (a2 % 360) * Math.PI / 180;
    return {
        path: [["M", x, y], ["l", r * Math.cos(a1), r * Math.sin(a1)], ["A", r, r, 0, +flag, 1, x + r * Math.cos(a2), y + r * Math.sin(a2)], ["z"]],
        fill: "hsb(" + clr + ", .75, .8)"
    };
};
points = [10, 20, 15];
total = 45;
start = 0;
paths = [];
for(i=0; i<=2; i++) {
  size = 360 / total * points[i];
  var slice = r.path();
  slice.attr({segment: [250, 250, 200, start, start + size], stroke: "#000", title: "Slice "+i});
  paths.push(slice);
  start += size;
}

I can then animate the slices in my paths array whenever I want, by animating the segment attribute:

newPoints = [5, 20, 20];
start = 0;
for(i=0; i<=2; i++) {
  size = 360 / total * newPoints[i];
  paths[i].animate({segment: [250, 250, 200, start, start + size]}, 800);
  paths[i].angle = start - size / 2;
  start += size;
}

Some of it I understand, some of it I don't. But the above code will work (I checked).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM