<!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>