3

I have a D3 Js Sankey diagram, with lots of data. At the end of the data are always companies. The company node is a simple circle. But around that circle i want a donut chart, with 2 values. The values are inside the company node as numsms and nummid. you can also see that in the picture below.

Example of the diagram: enter image description here

So I want around the company circles a donut chart. But I can't seem to get this to work, I've only found examples for donut charts as own svg.

My code for circles:

svg.selectAll(".node.circle")
        .append("circle")
        .attr("r", function(d) {
            if(d.node.indexOf("company-") > -1) {
                return company_circle_size(d);
            } else {
                return page_circle_size(d);
            }
        })
        .attr("cy", function(d) { return d.dy/2;})
        .attr("cx", function(d) {
            var cx = sankey.nodeWidth() - 30;
            if(d.node.indexOf("company-") > -1) {
                cx = cx + 15;
            }
            return cx;
        })
        .style("fill", function (d) {
            if(d.node.indexOf("company-") > -1) {
                if(d.name.indexOf("No data") > -1) {
                    return "grey";
                }
                var color = '';
                switch(d.status) {
                    case 'Approved':
                        color = 'green';
                        break;
                    case 'inactive ':
                        color = 'red';
                        break;
                    case 'initial':
                        color = 'yellow';
                        break;
                    case 'review':
                        color = 'blue';
                        break;
                    default:
                        color = 'grey';
                        break;
                }
                return color;
            }
            return "grey";
            //return d.color = color(d.name.replace(/ .*/, ""));
        })
        .style("fill-opacity", ".9")
        .style("shape-rendering", "auto")
        .style("stroke", function (d) {
            return d3.rgb(d.color).darker(2);
        })
        .append("title")
        .text(function (d) {
            if(d.node.indexOf("company-") > -1) {
                if(d.cpId != null) {
                    return d.name + "\n cpId: " + d.cpId;
                }
                return d.name;
            }
            return d.name + "\n" + format(d.value);
        });

In a for loop I replace the class name "node circle" to "node company".

$(selector).attr("class", "node company")

I've tried some things and I think the code needs to be placed here.

svg.selectAll('.company').each(function(companyNode) {
        var values = [[companyNode.numsms, companyNode.nummid]];
        var total = companyNode.numsms + companyNode.nummid;

        if(total > 0) {
            // create donut chart
        }
    });
Claire Nielsen
  • 1,881
  • 1
  • 14
  • 31
Marijn Kok
  • 121
  • 8
  • Please update your question with an example of your data. Tough to answer this without being able to re-create a complete example.... – Mark Apr 16 '15 at 13:55
  • The code is too big with nested items to the server. So i can't make a jsfidle without changing too much of my code. Also there is a lot of unnecessary code for this problem. If you mean the data as in the JSON string then i have this: http://jsfiddle.net/Mithek/f5e6L2su/ I put it in a jsfiddle because it's rather a long string. – Marijn Kok Apr 16 '15 at 14:21

3 Answers3

1

You can append a div to the node using foriegnObject. In that div pass your values to an inline jquery sparkline chart (line, pie, etc). Set the transparency of the div so that it doesn't block the diagram. Add your values to the original sankey data array(ie source,target,value,numsms,numid) and then call them in the append with d.numsms).

//sparkline plugin and setup...  http://omnipotent.net/jquery.sparkline/#s-docs
//something like the following, look at the fiddle for more info

node.append("foreignObject")
.attr("width", sankey.nodeWidth()*2)
.attr("height", function(d) { return d.dy/2 })
.attr("transform", function(d) { return "translate(" + (d.x+20) + "," + (d.y+10) + ")"; })
.append("xhtml:body")
.style("font", "14px 'Helvetica Neue'")
.html("<div>Inline Sparkline: <span class='inlinesparkline'>1,4,4,7,5,9,10</span></div>");

After adding the div to each node call the plugin to activate the inline charts.

$('.inlinesparkline').sparkline(); 

Have a look at my fiddle. It's not a sankey but it does show you how to implement foriegnObject.

d3.js diagram with inline charts!

Hope this helps.

Rob
  • 1,226
  • 3
  • 23
  • 41
1

Finally got back to this question.

Here's a quick example combining a sankey diagram containing a donut chart. I didn't fit it to your data, this is a generic example.

// if no pie data, just use rects as normal
node.filter(function(d){
    return !d.pieData;
  })
  .append("rect")
  .attr("height", function(d) {
    return d.dy;
  })
  .attr("width", sankey.nodeWidth())
  .style("fill", function(d) {
    return d.color = color(d.name.replace(/ .*/, ""));
  })
  .style("stroke", function(d) {
    return d3.rgb(d.color).darker(2);
  })
  .append("title")
  .text(function(d) {
    return d.name + "\n" + format(d.value);
  });

// set up donut chart stuff
var pColor = d3.scale.ordinal()
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

var arc = d3.svg.arc()
    .outerRadius(50)
    .innerRadius(20);

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

// if we have pie data, draw the donut chart
var g = node.filter(function(d){
    return d.pieData;
  })
  .append("g")
  .attr('transform', function(d,i){
     return 'translate('+d.dx/2+','+d.dy/2+')'; // proper position
  })
  .attr("class","donut")
  .selectAll(".arc")
  .data(function(d){
    return pie(d.pieData); // nested selection to assign data
  })
  .enter().append("g")
  .attr("class", "arc");

g.append("path")
  .attr("d", arc)
  .style("fill", function(d,i) { return color(i); });
Mark
  • 106,305
  • 20
  • 172
  • 230
-1

Sankey + Piechart implementation here: http://food.csaladen.es (though pie-chart resides in a static div, so move that above your node every time you evoke it)

csaladenes
  • 1,100
  • 1
  • 11
  • 27