Bubble tree in d3?
Asked Answered
S

3

24

Is there an equivalent implementation of a Bubble Tree in D3? In the link I provided, the Bubble Tree was implemented in RaphaelJS and jQuery.

enter image description here

Subjunctive answered 14/2, 2013 at 15:42 Comment(6)
Assuming you already searched the web, I think the odds of your question being answered here in the way you want are pretty slim. I think that a bubble chart is perfectly within the realm of possibilities with D3... Why don't you try and start making one and then ask questions surrounding the challenges that you come across in doing so?Gillam
@mbeasley: I have already started. But I'm letting this question stay. In almost all my previous questions, I was surprised when someone pointed me to an existing implementation hidden inside a small wiki somewhere :)Subjunctive
Fair enough. Be sure to post a link here to the implementation if you feel like sharing it. That would be great to see in D3! Good luckGillam
@mbeasley: Yes definitely. Thanks!Subjunctive
Please check InfoVis. They have similar graph like what you are looking may be it will give you some idea. But unlike Raphael it uses Canvas instead of SVG.Inviolable
You can use these examples : 1. Circle packing 2. Zoomable packing (modified circle packing) 3. Force-collapsible bubbles All these use data to be in tree format and visualize them in bubbles. They are easy to use, but you can make some changes if you want.Highpriced
M
1

The straight answer to your question is no.

Using the resources at https://github.com/okfn/bubbletree/tree/master/build, the information you already know, and the information provided on http://d3js.org/ and through D3's documentation on GitHub, you should be able to conjure up your own bubble tree for D3!

This is a piece of JavaScript I used a long time ago to visualize binary tree data:

var updateVisual;

updateVisual = function() {
    var drawTree, out;
    drawTree = function(out, node) {
        var col, gray, i, line, lineElt, lines, sub, _results, _results1;
        if (node.lines) {
            out.appendChild(document.createElement("div")).innerHTML = "<b>leaf</b>: " + node.lines.length + " lines, " + Math.round(node.height) + " px";
            lines = out.appendChild(document.createElement("div"));
            lines.style.lineHeight = "6px";
            lines.style.marginLeft = "10px";
            i = 0;
            _results = [];
            while (i < node.lines.length) {
                line = node.lines[i];
                lineElt = lines.appendChild(document.createElement("div"));
                lineElt.className = "lineblock";
                gray = Math.min(line.text.length * 3, 230);
                col = gray.toString(16);
                if (col.length === 1) col = "0" + col;
                lineElt.style.background = "#" + col + col + col;
                console.log(line.height, line);
                lineElt.style.width = Math.max(Math.round(line.height / 3), 1) + "px";
                _results.push(i++);
            }
            return _results;
        } else {
            out.appendChild(document.createElement("div")).innerHTML = "<b>node</b>: " + node.size + " lines, " + Math.round(node.height) + " px";
            sub = out.appendChild(document.createElement("div"));
            sub.style.paddingLeft = "20px";
            i = 0;
            _results1 = [];
            while (i < node.children.length) {
                drawTree(sub, node.children[i]);
                _results1.push(++i);
            }
            return _results1;
        }
    };
    out = document.getElementById("btree-view");
    out.innerHTML = "";
    return drawTree(out, editor.getDoc());
};

Just insert some circular elements and manipulate it a bit to style in a circular manor and you should have a good program set!

Medius answered 8/8, 2013 at 10:42 Comment(1)
You misunderstand. A bubble tree is a way of visualising hierarchical data; it has nothing to do with bubble sort. :)Osterman
S
1

Here you go. I didn't add the text or decorations, but it's the meat and potatoes:

function bubbleChart(config) {
	var aspectRatio = 1,
      margin = { top: 0, right: 0, bottom: 0, left: 0 },
      radiusScale = d3.scale.sqrt(),
      scan = function(f, data, a) {
        a = a === undefined ? 0 : a;
        var results = [a];
        data.forEach(function(d, i) {
          a = f(a, d);
          results.push(a);
        });
        return results;
      },
      colorScale = d3.scale.category20(),
      result = function(selection) {
		selection.each(function(data) {
			var outerWidth = $(this).width(),
          outerHeight = outerWidth / aspectRatio,
          width = outerWidth - margin.left - margin.right,
          height = outerHeight - margin.top - margin.bottom,
          smallestDimension = Math.min(width, height),
          sum = data[1].reduce(function(a, d) {
            return a + d[1];
          }, 0),
          radiusFractions = data[1].map(function(d) {
            return Math.sqrt(d[1] / sum);
          }),
          radiusNormalSum = radiusFractions.reduce(function(a, d) {
            return a + d;
          }, 0),
          scanned = scan(function(a, d) {
            return a + d;
          }, radiusFractions.map(function(d) {
            return d / radiusNormalSum;
          }), 0);
			radiusScale.domain([0, sum]).range([0, smallestDimension / 6]);
      var svg = d3.select(this).selectAll('svg').data([data]),
          svgEnter = svg.enter().append('svg');
			svg.attr('width', outerWidth).attr('height', outerHeight);
			var gEnter = svgEnter.append('g'),
          g = svg.select('g').attr('transform', 'translate(' + margin.left + ' ' + margin.top + ')'),
          circleRing = g.selectAll('circle.ring').data(data[1]),
          circleRingEnter = circleRing.enter().append('circle').attr('class', 'ring');
      circleRing.attr('cx', function(d, i) {
        return smallestDimension / 3 * Math.cos(2 * Math.PI * (scanned[i] + scanned[i + 1]) / 2) + width / 2;
      }).attr('cy', function(d, i) {
        return smallestDimension / 3 * Math.sin(2 * Math.PI * (scanned[i] + scanned[i + 1]) / 2) + height / 2;
      }).attr('r', function(d) {
        return radiusScale(d[1]);
      }).style('fill', function(d) {
        return colorScale(d[0]);
      });
      var circleMain = g.selectAll('circle#main').data([data[0]]),
          circleMainEnter = circleMain.enter().append('circle').attr('id', 'main');
      circleMain.attr('cx', width / 2).attr('cy', height / 2).attr('r', radiusScale(sum)).style('fill', function(d) {
        return colorScale(d);
      });
		});
	};
	result.aspectRatio = function(value) {
		if(value === undefined) return aspectRatio;
		aspectRatio = value;
		return result;
	};
	result.margin = function(value) {
		if(value === undefined) return margin;
		margin = value;
		return result;
	};
	return result;
}

var myBubbleChart = bubbleChart().margin({
  top: 1,
  right: 1,
  bottom : 1,
  left: 1
});
var data = ['Random Names, Random Amounts', [['Immanuel', .4], ['Pascal', 42.9], ['Marisa', 3.3], ['Hadumod', 4.5], ['Folker', 3.2], ['Theo', 4.7], ['Barnabas', 1.0], ['Lysann', 11.1], ['Julia', .7], ['Burgis', 28.2]]];
d3.select('#here').datum(data).call(myBubbleChart);
<div class="container">
  <div class="row">
    <div class="col-xs-12">
      <div id="here"></div>
    </div>
  </div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Stella answered 9/8, 2016 at 17:33 Comment(0)
I
0

You can use the pack layout , basically you can bind any data you want to the shapes in the graph and custom parameters for them to position well respect to each other. Another alternative would be the force layout.

Illaudable answered 21/5, 2015 at 10:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.