I am attempting to link d3 nodes by an ID instead of index (The node ID is generated by my application).
Here are my nodes:
"Nodes": [
{
"Id": "338",
"Name": "TEST NODE ONE",
"Url": "http://www.google.com"
},
{
"Id": "340",
"Name": "TEST NODE TWO",
"Url": "http://www.yahoo.com"
},
{
"Id": "341",
"Name": "TEST NODE THREE",
"Url": "http://www.stackoverflow.com"
},
{
"Id": "342",
"Name": "TEST NODE FOUR",
"Url": "http://www.reddit.com"
}
]
They are currently linked by index:
"links": [
{
"source": 0,
"target": 0,
"value": "0"
},
{
"source": 0,
"target": 1,
"value": "0"
},
{
"source": 1,
"target": 2,
"value": "0"
},
{
"source": 3,
"target": 2,
"value": "0"
}
]
However, I want to link them by "Id":
"Links": [
{
"Source": "338",
"Target": "338",
"Value": "0"
},
{
"Source": "338",
"Target": "340",
"Value": "0"
},
{
"Source": "340",
"Target": "341",
"Value": "0"
},
{
"Source": "342",
"Target": "341",
"Value": "0"
}
]
I've attempted the solution proposed here: https://groups.google.com/forum/#!msg/d3-js/LWuhBeEipz4/0kZIojCYvhIJ
by adding the following lines before calling force.nodes:
// make links reference nodes directly for this particular data format:
var hash_lookup = [];
// make it so we can lookup nodes in O(1):
json.Nodes.forEach(function(d, i) {
hash_lookup[d.Id] = d;
});
json.Links.forEach(function(d, i) {
d.source = hash_lookup[d.Source];
d.target = hash_lookup[d.Target];
});
I've tried debugging the above, but I can't manage to figure it out. I get the following error message (which usually means I haven't set links correctly):
Uncaught TypeError: Cannot read property 'weight' of undefined
Link to my full JS: http://jsfiddle.net/9sMrw/
In the update() function, links = d3. layout. tree(). links(nodes); is 'selecting' the nodes in the tree and their specified links in the JSON file.
D3's force layout uses a physics based simulator for positioning visual elements. Forces can be set up between elements, for example: all elements can be configured to repel one another. elements can be attracted to center(s) of gravity.
node() function in D3. js is used to return the first element in the selection.
Here is a straightforward way to do this:
var edges = [];
json.Links.forEach(function(e) {
var sourceNode = json.Nodes.filter(function(n) {
return n.Id === e.Source;
})[0],
targetNode = json.Nodes.filter(function(n) {
return n.Id === e.Target;
})[0];
edges.push({
source: sourceNode,
target: targetNode,
value: e.Value
});
});
force
.nodes(json.Nodes)
.links(edges)
.start();
var link = svg.selectAll(".link")
.data(edges)
...
Here is a working PLUNK. (You should fork it to be safe, in case I inadvertently delete it.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With