Ivan
Ivan

Reputation: 703

Fix position of force-graph node using D3.js

I'm using a force-graph D3 visualization from https://github.com/vasturiano/force-graph. This seems to provide great high-level API to create a force directed graph but I find it hard to customise as I'm new to Javascript.

<script src="//unpkg.com/force-graph"></script>
<script src="http://d3js.org/d3.v4.min.js" charset="utf-8"></script>

<script>

fetch('data.json').then(res => res.json()).then(data => {
      const Graph = ForceGraph()
      (document.getElementById('graph'))
        .graphData(data)
        .nodeAutoColorBy('group')
        .linkSource('source')
        .linkTarget('target')
})

</script>

The JSON data looks like this:

{
  "nodes": [
    {"id": "Myriel", "group": 1},
    {"id": "Napoleon", "group": 1}
  ],
  "links": [
    {"source": "Napoleon", "target": "Myriel", "value": 1},
    {"source": "Mlle.Baptistine", "target": "Myriel", "value": 8}
  ]
}

I am trying to fix the position of a particular node, for example id = Myriel to x=500, y=500. According to d3 force documentation, I need to specify fx and fy. How do I retrieve the id of the particular node to set the those attributes? Any help is greatly appreciated!

Upvotes: 0

Views: 1487

Answers (2)

Ivan
Ivan

Reputation: 703

I have found a solution:

.nodeVal(node => {         
  node.fx = 500;
  node.fy = 500
})

Using the nodeVal method, I can access the attributes of the nodes to fix it. Adding a if statement would allow me to change it only if it the specific nodes I need. Thanks for everyone's help!

Upvotes: 2

Bmil
Bmil

Reputation: 361

The API link that you've provided is really beautiful. It's such a complex chart to work with and it ticks almost every box.

However, it looks like the only way to adapt it to YOUR needs would be to hack into the js code which I would not advise.

Personally I would start with a simpler d3 version and customise from here.

For example: https://observablehq.com/@d3/force-directed-graph

Here, you'd need to customise the simulation.on("tick" function. Something like this:

node
    .attr("cx", d => d.x)
    .attr("cy", d => d.y)
    **.attr("fx", d => d.id === "Myrial" ? 500 : null)**
    **.attr("fy", d => d.id === "Myrial" ? 500 : null);**

`

OR for a similar approach to your example you could use Vega. That allows you to use fx and fy:

https://vega.github.io/vega/docs/transforms/force/

Upvotes: 0

Related Questions