Creating a sunburst diagram with dynamically chosen data source using D3

1.8k views Asked by At

I am trying to create an interactive sunburst diagram using D3, where the user can select a data source from a dropdown menu. Once the data source is selected, any existing sunburst would be erased and redraw using the new data. This is based off the D3 example called "Sequences Sunburst" http://bl.ocks.org/kerryrodden/7090426

Having done a bit of research, it looks like you need to follow the add/append/transition/exit pattern.

Here is a link to a semi-functioning example on JSFiddle: http://jsfiddle.net/DanGinMD/dhpsxm64/14/

When you select the first data source, the sunburst diagram is created. When you select the second data source, a second sunburst is added. Each one appears to be connected to its unique data source. How do I erase the first sunburst before drawing the second sunburst?

Here is the code for listener event for the dropdown box:

// an event listener that (re)draws the breadcrumb trail and chart
d3.select('#optionsList') 
  .on('change', function() {
  var newData = eval(d3.select(this).property('value'));
  createVisualization(newData);
});

Here is the code that draws the sunburst diagram:

function createVisualization(json) { 
  sysName = json.sysName;
  var titletext = sysName + " - Impact to Organization";
  d3.select("#title2").text(titletext);
  initializeBreadcrumbTrail();

  var vis = d3.select("#chart").append("svg:svg")
    .attr("width", width)
    .attr("height", height)
    .append("svg:g")
    .attr("id", "container")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

  var partition = d3.layout.partition()
    .size([2 * Math.PI, radius * radius])
    .value(function(d) { return d.size; });

  var arc = d3.svg.arc()
    .startAngle(function(d) { return d.x; })
    .endAngle(function(d) { return d.x + d.dx; })
    .innerRadius(function(d) { return Math.sqrt(d.y); })
    .outerRadius(function(d) { return Math.sqrt(d.y + d.dy);  });

  // Bounding circle underneath the sunburst, to make it 
  //  easier to detect  when the mouse leaves the parent g.
  vis.append("svg:circle")
    .attr("r", radius)
    .style("opacity", 0);

 // For efficiency, filter nodes to keep only those large enough to see.
var nodes = partition.nodes(json)
   .filter(function(d) {
    return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
    });

 var path = vis.data([json]).selectAll("path")
    .data(nodes)
    .enter().append("svg:path")
    .attr("display", function(d) { return d.depth ? null : "none"; })
    .attr("d", arc)
    .attr("fill-rule", "evenodd")
    .style("fill", function(d) { return colors[d.category]; })
    .style("opacity", 1)
    .on("mouseover", mouseover); 

   // Add the mouseleave handler to the bounding circle.
   d3.select("#container").on("mouseleave", mouseleave);

    // Get total size of the tree = value of root node from partition.
    totalSize = path.node().__data__.value; 

    path.exit().remove();
    nodes.exit().remove();
    arc.exit().remove();
    partition.exit().remove();
    vis.exit().remove();

}
1

There are 1 answers

0
Fabricator On BEST ANSWER

Note the following call that appends a new svg at visualization initialization:

var vis = d3.select("#chart").append("svg:svg")
    .attr("width", width)
    .attr("height", height)
    .append("svg:g")
    .attr("id", "container")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

You just need to remove any old svg before this statement:

  d3.select("#chart svg").remove();
  var vis = d3.select("#chart").append("svg:svg")
    .attr("width", width)
    .attr("height", height)
    .append("svg:g")
    .attr("id", "container")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

fiddle