Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 Circle Pack Layout with a horizontal arrangement

I'm trying to create a wordcloud with the D3 pack layout with a horizontal arrangement.

Instead of limiting the width, I am limiting the height.

The pack layout automatically disposes the circles with the larger one in the center and the others around him. If the height is limited, instead of expanding the circles disposition horizontally, it reduces the size of each circle.

How can I stop the layout from resizing the circles and start adding them to the sides if there is no more space around the larger one.

I want something like this: http://imgur.com/7MDnKHF

But I'm only achieving this: http://jsfiddle.net/v9xjra6c/

This is my current code:

var width,
    height,
    diameter,
    padding,
    format,
    pack,
    svg,
    node;

var initSizes = function() {
    var dimensions = { width: 900, height: 288 };
    width = dimensions.width;
    height = dimensions.height;
    diameter = Math.min(width, height);
    padding = 12;
    format = d3.format(',d');
};

var initLayout = function() {
    pack = d3.layout.pack()
        .sort(null)
        .size([width, height])
        .padding(padding);
};

var createSVG = function() {
    svg = d3.select('.chart-container').append('svg')
        .attr('width', width)
        .attr('height', height)
        .attr('class', 'bubble');
};

var createBubbles = function() {
    var dataset = pack.nodes(DATA);

    node = svg.selectAll('.node')
        .data(dataset.filter(function(d) { return !d.children; }))
        .enter().append('g')
        .attr('class', 'node')
        .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; });

    node.append('title')
        .text(function(d) { return d.name + ': ' + format(d.value); });

    node.append('circle')
        .attr('r', function(d) { return d.r; });

    node.append('text')
        .attr('dy', '.3em')
        .style('text-anchor', 'middle')
        .text(function(d) { return d.name.substring(0, d.r / 3); });
};

initSizes();

initLayout();

createSVG();

createBubbles();

Thanks!

like image 301
jphorta Avatar asked Nov 11 '15 14:11

jphorta


1 Answers

Your solution would be like merging this Example1 + Example2

So from Example 1 I have taken the mechanism to restrict the circles with in the bounds, such that it does not go beyond the svg height and width:

function tick(e) {
      node
          .each(cluster(10 * e.alpha * e.alpha))
          .each(collide(.5))
          //max radius is 50 restricting on the width
          .attr("cx", function(d) {  return d.x = Math.max(50, Math.min(width - 50, d.x)); })
          //max radius is 50 restricting on the height
          .attr("cy", function(d) { return d.y = Math.max(50, Math.min(height - 50, d.y)); });        }

Creating a scale for making radius

//so now for your data value which ranges from 0 to 100 you will have radius range from 5 to 500
var scale = d3.scale.linear().domain([0,100]).range([5, 50]);

Make the data as per Example2

var nodes = data.map(function(d){
  var i = 0,
      r = scale(d.value),
      d = {cluster: i, radius: r, name: d.name};  
  if (!clusters[i] || (r > clusters[i].radius)) {clusters[i] = d;}
  return d
});

Finally result will be looking like this

Note: You can reduce the height in the code and the circles will rearrange as per the space available.

Note: You can also play around the cluster to group similar nodes as in example in my case I have made a single group cluster.

Hope this helps!

like image 194
Cyril Cherian Avatar answered Nov 14 '22 13:11

Cyril Cherian