Quantcast
Channel: User i alarmed alien - Stack Overflow
Viewing all articles
Browse latest Browse all 42

Answer by i alarmed alien for Force directed graphs nodes stick to the center

$
0
0

You have to adapt your code slightly as it currently assumes that you're working with circle elements, where you specify the centres using cx and cy, but you are now using g elements, which use standard x and y coordinates.

First, remove the transform from the g element (that's a leftover from my demo code):

const node = svg.append("g")  .attr("stroke", "#fff")  .attr("stroke-width", 1.5).selectAll(".circles")  // note - should be .circles!  .data(nodes)  .enter()  .append("g")  .classed('circles', true)

and in the ticked() function, change the node updating code into a transform that works on g elements (which don't have cx or cy):

node.attr('transform', d => 'translate('+ d.x +','+ d.y +')' )

Demo:

var json = {"nodes":[{"id":"0","group":0},{"id":"1","group":1},{"id":"2","group":2},{"id":"3","group":3},{"id":"4","group":4},{"id":"5","group":5},{"id":"6","group":6},{"id":"7","group":7},{"id":"8","group":8},{"id":"9","group":9},{"id":"10","group":10},{"id":"11","group":11},{"id":"12","group":12},{"id":"13","group":13},{"id":"14","group":14},{"id":"15","group":15},{"id":"16","group":16},{"id":"17","group":17},{"id":"18","group":18},{"id":"19","group":19}],"links":[{"source":"0","target":"1","value":1},{"source":"0","target":"18","value":1},{"source":"0","target":"10","value":1},{"source":"0","target":"12","value":1},{"source":"0","target":"5","value":1},{"source":"0","target":"8","value":1},{"source":"1","target":"0","value":1},{"source":"1","target":"9","value":1},{"source":"1","target":"4","value":1},{"source":"2","target":"4","value":1},{"source":"2","target":"17","value":1},{"source":"2","target":"13","value":1},{"source":"2","target":"15","value":1},{"source":"3","target":"6","value":1},{"source":"4","target":"14","value":1},{"source":"4","target":"2","value":1},{"source":"4","target":"5","value":1},{"source":"4","target":"19","value":1},{"source":"4","target":"1","value":1},{"source":"5","target":"4","value":1},{"source":"5","target":"0","value":1},{"source":"6","target":"3","value":1},{"source":"7","target":"18","value":1},{"source":"7","target":"16","value":1},{"source":"8","target":"0","value":1},{"source":"9","target":"1","value":1},{"source":"10","target":"0","value":1},{"source":"10","target":"15","value":1},{"source":"12","target":"0","value":1},{"source":"13","target":"15","value":1},{"source":"13","target":"2","value":1},{"source":"14","target":"4","value":1},{"source":"15","target":"13","value":1},{"source":"15","target":"10","value":1},{"source":"15","target":"2","value":1},{"source":"16","target":"7","value":1},{"source":"17","target":"2","value":1},{"source":"18","target":"0","value":1},{"source":"18","target":"7","value":1},{"source":"19","target":"4","value":1},{"source":"19","target":"4","value":1}]};d3.selectAll("svg > *").remove();const svg = d3.select("svg");var width = 900var height = 900svg.style("width", width +'px').style("height", height +'px');const links = json.links.map(d => Object.create(d));const nodes = json.nodes.map(d => Object.create(d));const simulation = forceSimulation(nodes, links).on("tick", ticked);var categorical = [{"name": "schemeAccent","n": 8},{"name": "schemeDark2","n": 8}, ]var color = d3.scaleOrdinal(d3[categorical[1].name]);var drag = simulation => {  function dragstarted(d) {    if (!d3.event.active) simulation.alphaTarget(0.3).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) simulation.alphaTarget(0);    d.fx = null;    d.fy = null;  }  return d3.drag()    .on("start", dragstarted)    .on("drag", dragged)    .on("end", dragended);}const link = svg.append("g")  .attr("stroke", "#999")  .attr("stroke-opacity", 0.6)  .selectAll("line")  .data(links)  .enter().append("line")  .attr("stroke-width", d => Math.sqrt(d.value));const node = svg.append("g")  .attr("stroke", "#fff")  .attr("stroke-width", 1.5)  .selectAll(".circles")  .data(nodes)  .enter()  .append("g")  .classed('circles', true)  .call(drag(simulation))//    .attr('transform', d => 'translate('+ d.x +','+ d.y +')');const circle = node.append("circle")  .classed('circle', true)  .attr("r", 5)  .attr("fill", d => color(d.group))node  .append("text")  .classed('circleText', true)  .attr('dy', '0.35em')  .attr('dx', 5)  .text(d => "Node: "+ d.id);node.append("title").text(d => "Node: "+ d.id);function ticked() {  link    .attr("x1", d => d.source.x)    .attr("y1", d => d.source.y)    .attr("x2", d => d.target.x)    .attr("y2", d => d.target.y);  node.attr('transform', d => 'translate('+ d.x +','+ d.y +')')}function forceSimulation(nodes, links) {  return d3.forceSimulation(nodes)    .force("link", d3.forceLink(links).id(d => d.id))    .force("charge", d3.forceManyBody())    .force("center", d3.forceCenter());}
.circleText { fill: black; stroke: none }
<script src="//d3js.org/d3.v5.js"></script><svg></svg>

Viewing all articles
Browse latest Browse all 42

Trending Articles