Skip to content Skip to sidebar Skip to footer

Force Directed Graphs Nodes Stick To The Center

After following up from this question Insert text inside Circle in D3 chart My nodes are sticking to the center. I am not sure which property is directing my nodes and their x and

Solution 1:

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 = 900
svg.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]);


vardrag = simulation => {

  functiondragstarted(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
  }

  functiondragged(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
  }

  functiondragended(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);

functionticked() {
  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 + ')')
}

functionforceSimulation(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 }
<scriptsrc="//d3js.org/d3.v5.js"></script><svg></svg>

Post a Comment for "Force Directed Graphs Nodes Stick To The Center"