data_set = [ {name:"aaa"}, {name:"bbb"}, {name:"ccc"}, {name:"ddd"}, {name:"eee"}, {name:"fff"} ] ; link_set = [ {source:"aaa", target:"bbb"}, {source:"bbb", target:"ccc"}, {source:"ccc", target:"ddd"}, {source:"ddd", target:"eee"}, {source:"eee", target:"fff"}, {source:"fff", target:"aaa"}, ]; var width=600, height=300; var force_g = d3.select("#content").append("g") ; var links = force_g.selectAll(".link") .data(link_set) .enter() .append("line") .attr("class", "link") .attr("stroke", "#000") .attr("stroke-weight", 1) ; var circles = force_g.selectAll("circle") .data(data_set) .enter() .append("circle") .attr("class","test-circle") .attr("r", 5) .attr("fill","lightblue") .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended) ) ; var line_force = d3.forceSimulation() .nodes(data_set) .on("tick", ticked) .force("link", d3.forceLink(link_set) .id(function(d){ return d.name ; }) .distance(20) ) .force("center", d3.forceCenter(width/2, height/2)) .force('charge', d3.forceManyBody().strength(15)) .force("collision", d3.forceCollide(15)) ; function dragstarted(d) { if (!d3.event.active) line_force.alphaTarget(0.9).restart(); d.fx = d.x; d.fy = d.y; } function dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) line_force.alphaTarget(0); d.fx = null; d.fy = null; } function ticked(){ circles .attr("cx", function(d){ return d.x; }) .attr("cy", function(d){ return d.y; }) ; links .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; }); }
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script> <svg id="content" width="640" height="400" ></svg>