<!DOCTYPE html>
<html>
  <head>
    <title>d3-force-attract: mouse attract II</title>
  </head>

  <body>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://unpkg.com/d3-force-attract@latest"></script>
    <script>

var width = 960,
    height = 500,
    radius = 10;

var nodes = d3.range(50).map(function (d) {
  return {
    x: width * Math.random(),
    y: height * Math.random(),
    r: radius,
    inertia: 0.05 + 0.15 * Math.random()
  };
});

// set up attract force to pull nodes toward mouse location.
// set attract strength per node, to prevent nodes from bunching up
// (and to demonstrate per-node attract parameters).
var simulation = d3.forceSimulation()
  .force('attract', d3.forceAttract()
    .target([width / 2, height / 2])
    .strength(function (d) { return d.inertia; }))
  .force('collide', d3.forceCollide(function (d) { return d.r; }))
  .on('tick', layoutTick)
  .nodes(nodes);
  
var svg = d3.select('body').append('svg')
    .attr('width', width)
    .attr('height', height);

var node = svg.selectAll('circle')
  .data(nodes)
  .enter().append('circle')
    .attr('cx', function (d) { return d.x; })
    .attr('cy', function (d) { return d.y; })
    .attr('r', function (d) { return d.r; });

svg.on('mousemove', function () {
    simulation.force('attract').target(d3.mouse(this));
    simulation
      .alphaTarget(0.3)
      .restart();
  });
  
function layoutTick (e) {
  node
    .attr('cx', function (d) { return d.x; })
    .attr('cy', function (d) { return d.y; });
}

    </script>
  </body>
</html>