Bubble clusters

by b_g_v

HTML

<p>Limited synonyms-type, max four words distance with intermediate nodes</p>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="application/json" id="data">
{
  "nodes": [
    {
      "color": "orange", 
      "size": 9, 
      "atom": "AAP Video"
    }, 
    {
      "color": "green", 
      "size": 3, 
      "atom": "ABC News"
    }, 
    {
      "color": "blue", 
      "size": 2, 
      "atom": "Alex Murray"
    }, 
    {
      "color": "blue", 
      "size": 4, 
      "atom": "Alexander Petrov"
    }, 
    {
      "color": "blue", 
      "size": 2, 
      "atom": "Attorney General"
    }, 
    {
      "color": "orange", 
      "size": 3, 
      "atom": "Barack Obama"
    }, 
    {
      "color": "blue", 
      "size": 14, 
      "atom": "Bob Woodward"
    }, 
    {
      "color": "blue", 
      "size": 6, 
      "atom": "Capitol Hill"
    }, 
    {
      "color": "orange", 
      "size": 2, 
      "atom": "Chairman Chuck"
    }, 
    {
      "color": "blue", 
      "size": 2, 
      "atom": "Chief Executive"
    }, 
    {
      "color": "blue", 
      "size": 3, 
      "atom": "Chief of Staff"
    }, 
    {
      "color": "green", 
      "size": 5, 
      "atom": "Christine Middap"
    }, 
    {
      "color": "blue", 
      "size": 2, 
      "atom": "Chuck Grassley"
    }, 
    {
      "color": "blue", 
      "size": 5, 
      "atom": "Cold War"
    }, 
    {
      "color": "blue", 
      "size": 8, 
      "atom": "Colin Kaepernick"
    }, 
    {
      "color": "orange", 
      "size": 15, 
      "atom": "Defense Secretary Jim Mattis"
    }, 
    {
      "color": "green", 
      "size": 4, 
      "atom": "Democratic Party"
    }, 
    {
      "color": "orange", 
      "size": 2, 
      "atom": "Dianne Feinstein"
    }, 
    {
      "color": "orange", 
      "size": 5, 
      "atom": "Discuss 30"
    }, 
    {
      "color": "green", 
      "size": 6, 
      "atom": "Disease Control"
    }, 
    {
      "color": "blue", 
      "size": 4, 
    ...

CSS

text {
  /*stroke: black;*/
  font: 10px sans-serif;
}
circle {
    stroke: #565352;
    stroke-width: 1;
}

JavaScript

var dataNode = document.getElementById('data').innerHTML,
    graphData = JSON.parse(dataNode);

var width = 1900,
    height = 800,
    padding = 20, // separation between same-color nodes
    clusterPadding = 40, // separation between different-color nodes
    maxRadius = 100;

//unique cluster/group id's and colors
var cs = [],
    colors = [],
    data = graphData["nodes"];

data.forEach(function(d){
    if(!colors.includes(d.color) && typeof(d.color) !== "undefined") {
        colors.push(d.color);
    }
    colorIndex = colors.indexOf(d.color);
    if(colorIndex >-1 && !cs.includes(colorIndex)) {
        cs.push(colorIndex);
    }
});

var color = d3.scale.ordinal().range(colors);

var radius = d3.scale.sqrt().range([0, 4]);

var n = data.length, // total number of nodes
    m = cs.length; // number of distinct clusters

//create clusters and nodes
var clusters = new Array(m);
var nodes = [];
for (var i = 0; i<n; i++){
    var node = create_nodes(data, i);
    if(node){
        nodes.push(node);
    }
}

var force = d3.layout.force()
    .nodes(nodes)
    .size([width, height])
    .gravity(0.001)
    .charge(0)
    .on("tick", tick)
    .start();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var node = svg.selectAll("circle")
    .data(nodes)
    .enter().append("g").call(force.drag);

node.append("circle")
    .style("fill", function (d) {
        return color(d.cluster);
    })
    .attr("r", function(d){return d.radius})

node.append("text")
      .attr("dy", ".3em")
      .style("text-anchor", "middle")
      .text(function(d) { return d.text; });

var drag = force.drag()
  .on("dragstart", function(d) {
	   d3.select(this).classed("fixed", d.fixed = true);
});

function create_nodes(data, node_counter) {
  if(data[node_counter].atom.charAt(0) != '_'){
    var i = cs.indexOf(colors.indexOf(data[node_counter].color)),
        r = Math.sqrt((i + 1) / m * -Math.log(Math.random())) * maxRadius,
        d...