Edit in JSFiddle

// Initial setup
var panel = d3.select('#panel')
var w = 500;
var h = 200;
var padding = 10;
var kerning = 0;
var trigger_buf = 50;
var svg = d3.select('#svg')
            .style('width', '100%')
            .attr('height', h)
            .style('font-size', '2.5em')
            .style('font-family', '"PT Serif"');
var str1 = transform('the neural bit');
var str2 = transform('brian hulette');
var mouse_node = {};

var curr_str = str1;

// Turn strings into lists of objects with some additional information
function transform(str) {
  var x = d3.scale.ordinal()
        .domain(d3.range(str.length))
        .rangePoints([20, w-20], 1);
  var rtrn = []
  var char_count = {};
  var tester = svg.append('text')
  var curr_x = padding;
  var bbox, this_object, is_space;
  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;
    }
    is_space = str[i] == " "
    tester.text(is_space ? "T" : str[i])
          .each(function(d) {
            bbox = this.getBBox();
          });
 
    curr_x += bbox.width/2;

    // These are the objects were adding to the list
    // c:       the char
    // count:   # of previous occurrences of this letter (used for the d3 key)
    // x, y:    initial positions for force layour
    // cx, cy:  assigned positions for gravity force - letters will be attracted
    //          here
    // radius:  used for collision detection
    // w, h:    width and height of the letter
    this_object = {
      c: str[i],
      count: char_count[str[i]],
      x: curr_x,
      y: h/2,
      cx: curr_x,
      cy: h/2,
      radius: is_space ? 0 : bbox.width/2 - 2,
      w: bbox.width,
      h: bbox.height
    };
    rtrn.push(this_object);
    curr_x += bbox.width/2;
  }
  tester.remove()
  return rtrn;
}

// Use this key for d3 selections, so that when we change out strings we
// associate corresponding characters in the anagrams correctly
function key(d) {
  return d.c + d.count;
}

// Create the initial text objects
var text = svg.selectAll('text')
    .data(str1)
    .enter()
    .append('text')
    .attr('text-anchor', 'middle')
    .attr('alignment-baseline', 'middle')
    .attr('x', function (d, i) {
      return d.x - w/2
    })
    .attr('y', function(d, i) {
      return d.y + h/2;
    })
    .attr('fill', 'black')
    .text(function (d) {
      return d.c;
    });

// Get minimum and maximum x,y values for all the letters
// We will use this to define a rectangle around the 
// letters where mouseenter will trigger the transition
var min_x = d3.min(text.data(), function(d) {return d.x - d.w/2;}) - trigger_buf;
var max_x = d3.max(text.data(), function(d) {return d.x + d.w/2;}) + trigger_buf;
var min_y = d3.max(text.data(), function(d) {return d.y - d.h/2;}) - trigger_buf;
var max_y = d3.max(text.data(), function(d) {return d.y + d.h/2;}) + trigger_buf;

var trigger_rect = svg.append('rect')
  .attr('x', Math.max(0, min_x))
  .attr('width', max_x - min_x)
  .attr('y', Math.max(0, min_y))
  .attr('height', max_y - min_y)
  .attr('fill-opacity', '0')

// Create force layout
var force = d3.layout.force()
  .nodes([mouse_node].concat(str1))
  .links([])
  .gravity(0)
  .size([w, h])
  .charge(0);

force.on("tick", function(e) {
  // Attract each node towards its assigned position
  text.each(gravity(.15*e.alpha));

  // Do collision detection between every node
  var q = d3.geom.quadtree(curr_str);
  var i = 0;
  while (++i < curr_str.length) q.visit(collide(curr_str[i]));

  // Move each character to its assigned position
  cw = svg.node().getBoundingClientRect().width;
  ch = svg.node().getBoundingClientRect().height;
  text
    .attr('x', function(d) { 
      var x = Math.max(d.w/2, Math.min(cw - d.w/2, d.x));
      return x;
    })
    .attr('y', function(d) { 
      var y = Math.max(d.h/2, Math.min(ch - d.h/2, d.y));
      return y;
    });
});

// Attract each letter to its focus point
function gravity(alpha) {
  return function(d) {
    d.y += (d.cy - d.y) * alpha;
    d.x += (d.cx - d.x) * alpha;
  };
}

// Perform collisions between each nodes
function collide(node) {
  var r = node.radius + 16,
      nx1 = node.x - r,
      nx2 = node.x + r,
      ny1 = node.y - r,
      ny2 = node.y + r;
  return function(quad, x1, y1, x2, y2) {
    if (quad.point && (quad.point !== node)) {
      var x = node.x - quad.point.x,
          y = node.y - quad.point.y,
          l = Math.sqrt(x * x + y * y),
          r = node.radius + quad.point.radius;
      if (l < r) {
        l = (l - r) / l * .5;
        node.x -= x *= l;
        node.y -= y *= l;
        quad.point.x += x;
        quad.point.y += y;
      }
    }
    return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
  };
}

// Handle mouse/touch events
// enter: switch between strings using toggle() and turn on charge for node that
//        follows mouse
// leave: turn off charge for mouse node
// move:  move mouse node to actual mouse position
var active = true;
function toggle(str) {
  force.nodes([mouse_node].concat(str));

  old_str = text.data();
  old_str.forEach(function(item) {
    str.forEach(function(other) {
      if (key(item) == key(other)) {
        other.x = item.x;
        other.y = item.y
        other.px = item.px;
        other.py = item.py;
      }
    });
  });
  text.data(str, key);
  //circles.data(str, key);
  curr_str = str;
  force.start();
}

function do_toggle() {
  console.log('toggling!');
  if (active) {
    toggle(str2); 
  } else {
    toggle(str1);
  }
  active = !active;
}

function startmouse() { 
  console.log('activating charge!');
  force.charge(function(d, i) { return i == 0 ? -1000 : 1; });
  force.start();
}

function endmouse() { 
  console.log('mouseleave');
  force.charge(0);
  force.start();
}

function movemouse() { 
  var p1 = d3.mouse(this);
  mouse_node.x = p1[0];
  mouse_node.y = p1[1];
  force.resume();
}

trigger_rect.on('mouseenter', do_toggle);
svg.on('mouseenter', startmouse);
svg.on('touchstart',  startmouse);
svg.on('mouseleave',  endmouse);
svg.on('touchend',    endmouse);
svg.on('touchcancel', endmouse);
svg.on('mousemove',   movemouse);
svg.on('touchmove',   movemouse);

// Start up the force layout once everything is defined
force.start();