Stacked D3JS Bubble Chart Stacked D3JS Bubble Chart json json

Stacked D3JS Bubble Chart


In the example you provided, he's definitely using a force layout, which is a bit more complicated that the Bubble Chart you're using. You'll have to take into consideration things like collisions and animation.

Why not just have a look at the JavaScript he used to generate it.

Jim Vallandingham wrote an extensive tutorial on Bubble Clouds, which should get you started.

To create the split in the middle of the cirlce as a way of doing some form of data comparison, "clip-paths" are the way forward:

  • Append two circles, one for each data-set.
  • Append two clip-path, one for each data-set
  • Append a rectange to each clip-path.
  • Set the rectangle x attributes and width, which defines the position of the split in the middle. This has to be a function of the data.
  • Crop the rectangles and circles

Here's the code:

var nodeEnter = node.enter().append("a")      .attr("class", "g-node")      .call(force.drag);  var democratEnter = nodeEnter.append("g")      .attr("class", "g-democrat");  democratEnter.append("clipPath") // clip-path to crop the rectangle      .attr("id", function(d) { return "g-clip-democrat-" + d.id; })    .append("rect");  democratEnter.append("circle");  var republicanEnter = nodeEnter.append("g")      .attr("class", "g-republican");  republicanEnter.append("clipPath") // Clip-path to crop the rectangle     .attr("id", function(d) { return "g-clip-republican-" + d.id; })     .append("rect");  republicanEnter.append("circle");  node.selectAll("rect")      .attr("y", function(d) { return -d.r - clipPadding; })      .attr("height", function(d) { return 2 * d.r + 2 * clipPadding; });  // Defining the x-attr and width of the rectangle, which effectively splits the circle  node.select(".g-democrat rect")      .attr("x", function(d) { return -d.r - clipPadding; })       .attr("width", function(d) { return 2 * d.r * d.k + clipPadding; });  node.select(".g-republican rect")      .attr("x", function(d) { return -d.r + 2 * d.r * d.k; })      .attr("width", function(d) { return 2 * d.r; });  // Setting the clip-path to crop the circles  node.select(".g-democrat circle")      .attr("clip-path", function(d) { return d.k < 1 ? "url(#g-clip-democrat-" + d.id + ")" : null; });  node.select(".g-republican circle")      .attr("clip-path", function(d) { return d.k > 0 ? "url(#g-clip-republican-" + d.id + ")" : null; });

This should generate something like this:

<g class="g-democrat">    <clipPath id="g-clip-democrat-43">        <rect y="-63.36487389363757" height="126.72974778727514" x="-63.36487389363757" width="59.449375597303515">        </rect>    </clipPath>    <circle clip-path="url(#g-clip-democrat-43)" r="59.36487389363757"></circle></g><g class="g-republican">    <clipPath id="g-clip-republican-43">        <rect y="-63.36487389363757" height="126.72974778727514" x="-3.915498296334057" width="118.72974778727514">        </rect>    </clipPath>    <circle clip-path="url(#g-clip-republican-43)" r="59.36487389363757"></circle></g>