D3 Circle Pack Layout with a horizontal arrangement
Asked Answered
D

1

6

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: https://i.sstatic.net/nZocQ.jpg

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!

Devilkin answered 11/11, 2015 at 14:42 Comment(1)
You would need to modify the layout for this; the current implementation doesn't allow to control this.Sayles
C
4

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!

Concertgoer answered 12/11, 2015 at 7:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.