Home Ask Login Register

Developers Planet

Your answer is one click away!

Cris Benois February 2016

Please could someone explain how data is handled in this 3D piechart?

I'm trying to grasp how the functions in Donut3D.js -> http://plnkr.co/edit/g5kgAPCHMlFWKjljUc3j?p=preview handle the inserted data:

Above all, where is it set that the data's startAngle is set at 0 degrees? I want to change it to 45º, then to 135º, 225º and 315º (look at the image above).

enter image description here

I've located this function:

        Donut3D.draw = function(id, data, x /*center x*/, y/*center y*/, 
                rx/*radius x*/, ry/*radius y*/, h/*height*/, ir/*inner radius*/){

            var _data = d3.layout.pie().sort(null).value(function(d) {return d.value;})(data);

            var slices = d3.select("#"+id).append("g").attr("transform", "translate(" + x + "," + y + ")")
                .attr("class", "slices");              

            slices.selectAll(".innerSlice").data(_data).enter().append("path").attr("class", "innerSlice")
                .style("fill", function(d) { 
                    return d3.hsl(d.data.color).darker(0.7); })
                .attr("d",function(d){ 
                    return pieInner(d, rx+0.5,ry+0.5, h, ir);})
                .each(function(d){this._current=d;});

            slices.selectAll(".topSlice").data(_data).enter().append("path").attr("class", "topSlice")
                .style("fill", function(d) { 
                    return d.data.color; })
                .style("stroke", function(d) { 
                    return d.data.color; })
                .attr("d",function(d){ 
                    return pieTop(d, rx, ry, ir);})
                .each(function(d){this._current=d;});

            slices.selectAll(".outerSlice").data(_data).enter().append("path").attr("class", "outerSlice")
                .style("fill", function(d) { 
           

Answers


Mehdi El Fadil February 2016

Changing the default start angle

Donut3D users d3's pie layout function here, which has a default startAngle of 0.

If you want to change the start angle, you should modify donut3d.js.

In the first place, you should certainly avoid to use 3d pie/donut charts, if you care about usability and readability of your visualizations - explained here.

Fixing bottom corner layout

The endAngle you are using is not correct, causing the "light blue" slice to overlap the "blue" one. Should be 405 (i.e. 45 + 360) instead of 415.

var _data = d3.layout.pie()
  .startAngle(45*Math.PI/180)
  .endAngle(405*Math.PI/180)

Then, the "pieOuter" angles calculation should be updated to behave correctly. The arc which doesn't work is the one where endAngle > 2 * PI, and the angle computation should be updated for it.

This does the trick (don't ask me why):

// fix right-side outer shape
if (d.endAngle > 2 * Math.PI) {
  startAngle = Math.PI / 120
  endAngle = Math.PI/4
}

demo: http://plnkr.co/edit/wmPnS9XVyQcrNu4WLa0D?p=preview


Mark February 2016

Here's a corrected function which allows rotation.

First, modify function signature to include rotate variable:

Donut3D.draw = function(id, data, x /*center x*/ , y /*center y*/ ,
        rx /*radius x*/ , ry /*radius y*/ , h /*height*/ , ir /*inner radius*/, rotate /* start angle for first slice IN DEGREES */ ) {

In the draw function, modify angles. Instead of screwing with pie angles, I'd do it to the data directly:

_data.forEach(function(d,i){
  d.startAngle += rotate * Math.PI/180; //<-- convert to radians
  d.endAngle += rotate * Math.PI/180;
});

Then you need to correct the pieOuter function to fix the drawing artifacts:

function pieOuter(d, rx, ry, h) {

    var startAngle = d.startAngle,
        endAngle = d.endAngle;

    var sx = rx * Math.cos(startAngle),
      sy = ry * Math.sin(startAngle),
      ex = rx * Math.cos(endAngle),
      ey = ry * Math.sin(endAngle);

    // both the start and end y values are above
    // the middle of the pie, don't bother drawing anything
    if (ey < 0 && sy < 0)
      return "M0,0";

    // the end is above the pie, fix the points
    if (ey < 0){
      ey = 0;
      ex = -rx;
    }
    // the beginning is above the pie, fix the points.
    if (sy < 0){
      sy = 0;
      sx = rx;
    }

    var ret = [];
    ret.push("M", sx, h + sy, "A", rx, ry, "0 0 1", ex, h + ey, "L", ex, ey, "A", rx, ry, "0 0 0", sx, sy, "z");
    return ret.join(" ");

}

Here's the full code

Post Status

Asked in February 2016
Viewed 1,923 times
Voted 5
Answered 2 times

Search




Leave an answer


Quote of the day: live life