I am new to D3.js and I am trying to make some animation with my graph,
but I can't resolve a problem with the .get() method called on a d3.map for D3 version 6.
When I run the code it throws an error:
nodeById.get is not a function
My code is based on: https://bl.ocks.org/ctufts/bd6956a45ea69734f5909c8b526c13b5
//some fetch data in json file
d3.json("someURLjsonfile").then(function (graph) {
let nodes = graph.nodes,
nodeById = d3.map(nodes, function (d) {
return d.id;
}),
links = graph.links,
bilinks = [];
links.forEach(function (link) {
var s = nodeById.get(link.source), // <-- error
t = nodeById.get(link.target), // <-- error
i = {}; // intermediate node
nodes.push(i);
links.push({
source: s,
target: i
}, {
source: i,
target: t
});
bilinks.push([s, i, t]);
});
Your problem is caused by some rather unfortunate re-design of the API. As of D3 v6 the d3-collection module was deprecated and removed from the D3 bundle. That module contained the d3.map() constructor method that would create a d3.map object, i.e. one of D3's internal map implementations mimicking the native JavaScript Map. This method has been around a while but has lost importance once ES6 feature became available and was therefore removed.
Sadly, with version 2 of the d3-array module a method with the same name was introduced which is basically equivalent to the native array.map() or Array.from() methods:
# d3.map(iterable, mapper) · Source
Returns a new array containing the mapped values from iterable, in order, as defined by given mapper function. Equivalent to array.map and Array.from:
Since d3-array v2 was introduced to the bundle with the same version 6 that also removed d3-collection the d3.map property is still available, however, its meaning has changed.
Your code seems to have been written for D3 <v6 and breaks because of the changes laid out above. The new d3.map() is a mapper function not a constructor; it returns an array which does not feature a .get() method, hence, the error.
To fix the issue you can change your code to directly use the built-in Map object instead:
nodeById = new Map(Array.from(nodes, d => [d.id, d]));
With the rest untouched your code should be running as expected.