drag = simulation => { function dragstarted(event) { if (!event.active) simulation.alphaTarget(0.3).restart(); event.subject.fx = event.subject.x; event.subject.fy = event.subject.y; } function dragged(event) { event.subject.fx = event.x; event.subject.fy = event.y; } function dragended(event) { if (!event.active) simulation.alphaTarget(0); event.subject.fx = null; event.subject.fy = null; } return d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended); } var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"); var simulation = d3.forceSimulation() .force("charge", d3.forceManyBody().strength(-200)) .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(40)) .force("x", d3.forceX(width / 2)) .force("y", d3.forceY(height / 2)) .on("tick", ticked); var link = svg.selectAll(".link"), node = svg.selectAll(".node"); graph = {{data}} simulation.nodes(graph.nodes); simulation.force("link").links(graph.links); link = link .data(graph.links) .enter().append("line") .attr("class", "link"); node = node .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 6) .style("fill", function(d) { return d.id; }); function ticked() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }