'"Uncaught (in promise) Error: node not found: undefined" when using D3 and JS in browser
I'm new to Node and especially new to D3, and am trying to design a force directed graph. The
forceLink().id
section throws an error in the browser:
Uncaught (in promise) Error: node not found: undefined
at find (d3-force.js:124:11)
at initialize (d3-force.js:157:24)
at Function.force.initialize (d3-force.js:186:5)
at initializeForce (d3-force.js:273:13)
at Object.force (d3-force.js:307:89)
at drawGraph (app.js:116:10)
at app.js:220:1
Numerous tutorials and other answers on this site explain my current approach as the correct method, but I may be missing something obvious, such as changes in the API or something else. Can anyone explain why it does not run correctly? Any help would be much appreciated.
Code:
import * as d3 from "https://cdn.skypack.dev/d3@7";
async function drawGraph(){
var graphData = {
nodes : [
{ login: 'Bob' },
{ login: 'Carrol' },
{ login: 'John' },
{ login: 'Tanya' },
{ login: 'Sally' },
{ login: 'Louis' }
],
links : [
{ login: 'Bob', parent: 'Carrol', score: '5' },
{ login: 'Carrol', parent: 'John', score: '396' },
{ login: 'John', parent: 'Tanya', score: '387' },
{ login: 'Tanya', parent: 'Tanya', score: '4' },
{ login: 'Tanya', parent: 'John', score: '247' },
{ login: 'John', parent: 'Carrol', score: '86' },
{ login: 'Carrol', parent: 'Tanya', score: '101' },
{ login: 'Carrol', parent: 'Carrol', score: '161' },
{ login: 'John', parent: 'Sally', score: '150' },
{ login: 'Sally', parent: 'Sally', score: '2162' },
{ login: 'Sally', parent: 'Tanya', score: '451' },
{ login: 'John', parent: 'John', score: '1133' },
{ login: 'Bob', parent: 'John', score: '22' },
{ login: 'Tanya', parent: 'Bob', score: '177' },
{ login: 'John', parent: 'Louis', score: '215' },
{ login: 'John', parent: 'Bob', score: '208' },
{ login: 'Louis', parent: 'Bob', score: '15' },
{ login: 'Bob', parent: 'Louis', score: '53' },
{ login: 'Louis', parent: 'Sally', score: '188' }
]
};
const width = window.innerWidth
const height = window.innerHeight
const svg = d3.select('svg')
.attr('width', width)
.attr('height', height)
const simulation = d3.forceSimulation(graphData.nodes)
.force('charge', d3.forceManyBody().strength(-20))
.force('center', d3.forceCenter(width / 2, height / 2))
.force('link', d3.forceLink(graphData.links).
id(function(d){
return d.login;})
)
.on("tick", ticked);
// function getNodeColor(node) {
// return node.level === 1 ? 'red' : 'gray'
// }
const nodeElements = svg.append('g')
.selectAll('circle')
.data(graphData.nodes)
.enter().append('circle')
.attr('r', 10)
.attr('fill', function(d){
return 'orange';
})
.attr("stroke", "yellow");
const textElements = svg.append('g')
.selectAll('text')
.data(graphData.nodes)
.enter().append('text')
.text(node => node.login)
.attr('font-size', 15)
.attr('dx', 15)
.attr('dy', 4)
const linkElements = svg.append('g')
.selectAll('line')
.data(graphData.links)
.enter().append('line')
.attr('stroke-width', function(d){
return 3;
})
.attr('stroke', 'pink');
function ticked(){
nodeElements
.attr("cx", function(d){
return d.x;
})
.attr("cy", function(d){
return d.x;
});
textElements
.attr("x", function(d){
return d.x;
})
.attr("y", function(d){
return d.x;
});
linkElements
.attr('x1', function(d){
return d.parent.x;
})
.attr('y1', function(d){
return d.parent.y;
})
.attr('x2', function(d){
return d.login.x;
})
.attr('y2', link => function(d){
return d.login.y;
});
}
simulation.nodes(graphData.nodes).on('tick', () => {
nodeElements
.attr("cx", function(d){
return d.x;
})
.attr("cy", function(d){
return d.x;
});
textElements
.attr("x", function(d){
return d.x;
})
.attr("y", function(d){
return d.x;
});
linkElements
.attr('x1', function(d){
return d.parent.x;
})
.attr('y1', function(d){
return d.parent.y;
})
.attr('x2', function(d){
return d.login.x;
})
.attr('y2', link => function(d){
return d.login.y;
})
});
}
drawGraph();
I have tried to change the makeup of the lists (separating them into different list for nodes and links). It also gives an error regardless of it being async or not, and I have tried for forceLink to just use graphData instead of graphData.links as a parameter, which allows the nodes to render but not the links and still throws an error:
Error: <line> attribute y2: Expected length, "function(d){\r\n …".
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
