JSFiddle - React, Tailwind, and code Playground

by theneuralbit

HTML

<div id="chart"></div>

JavaScript

var w = 400,
    h = 200;

function key(d) {
  return d.c + d.count;
}

function strParse(str) {
  var rtrn = []
  var char_count = {};
  for (var i = 0; i < str.length; i++) {
    if (typeof char_count[str[i]] !== 'undefined') {
      char_count[str[i]] += 1;
    } else {
      char_count[str[i]] = 0;
    }
    rtrn.push({
      c: str[i],
      count: char_count[str[i]]
    });
  }
  return rtrn;
}


root = {};
root.radius = 0;
root.fixed = true;

var nodes = [root];
nodes.push.apply(nodes, strParse('brian hulette'));
console.log(nodes);
var color = d3.scale.category10();

var force = d3.layout.force()
    .gravity(0.05)
    .charge(function(d, i) { return i ? 0 : -2000; })
    .nodes(nodes)
    .size([w, h]);

force.start();

var svg = d3.select("#chart").append("svg:svg")
    .attr("width", w)
    .attr("height", h);

svg.selectAll("text")
    .data(nodes.slice(1), key)
  .enter().append("svg:text")
    .text(function(d) { return d.c; });

force.on("tick", function(e) {
  var q = d3.geom.quadtree(nodes),
      i = 0,
      n = nodes.length;
  var k = .05 * e.alpha;

  // Push nodes toward their designated focus.
  svg.selectAll("text")
      .attr("y", function(d, i) {
        d.y += (h/2 - d.y) * k;
        return d.y; 
      })
      .attr("x", function(d, i) {
        d.x += (15*i - d.x) * k;
        return d.x; 
      });
});

svg.on("mouseenter", function() {
  force.charge(function(d, i) { return i ? 0 : -2000; }); 
  svg.selectAll("text")
   .data(strParse('the neural bit'), key);
});

svg.on("mouseleave", function() {
 force.charge(0); 
});

svg.on("mousemove", function() {
  var p1 = d3.mouse(this);
  root.px = p1[0];
  root.py = p1[1];
  force.resume();
});