deathlock
deathlock

Reputation: 2837

d3.js force directed graph: How to make node size depends on the value of the links?

I have this kind of data:

var nodes = [
{
    "id": "A",
    "label": "Data A",
    "group": "0",
    "level": "0"
}, {
    "id": "B",
    "label": "Data B",
    "group": "1",
    "level": "1"
},
// etc //
]

var links = [
{
    "source": "A",
    "target": "B",
"strength": "0.5",
    "value": "276"
}, {
    "source": "A",
    "target": "C",
"strength": "0.5",
"value": "866"
},
// etc //
]

I've been trying to set the nodes radius size according to the value from the links that have said node as its target.

So for example, node B should have its size according to the value of 276 (the link that have node B as its target).

This what I use:

var nodeElements = g.append("g") 
    .attr("class", "nodes")
    .selectAll("circle")
    .data(nodes)
    .enter().append("circle")
    .attr("r", function(node,link){
          var radius = 12;
          if (node.level == 0) radius = radius * 2; // Setting up the main node as bigger than others

          node.weight = link.filter(function(link) {
             if (link.target.index == node.index){
               var linkValue = link.value;
               if (linkValue > 500) ? (radius = 12) : (radius = 6);
             }
          });

          return radius;
      })
    .attr("fill", getNodeColor)
    .attr("stroke", "#fff")
    .attr('stroke-width', 2)
    .on('mouseover', selectNode)

That doesn't seem to work though. Says it doesn't recognize the link.filter, something I've taken from here. I'm using d3.js v4.

Tried looking up for clues but still got no hints. Any ideas?

Upvotes: 0

Views: 2015

Answers (1)

RecencyEffect
RecencyEffect

Reputation: 756

There are several things that need to change, but first you should understand that you are not automatically adding links to the node's data.

So the purpose of the filter statement seems to be to find the corresponding link in that array, based on index. There is no link variable passed into the outer function, but instead you should be searching through the links array defined above for one link that has target with the node's id.

If you only need one link, and not all of them, use Array.prototype.find. But filter and find work the same way - the anonymous function defined is called on each item in the array. find stops at the first found object, while filter returns all matches.

.attr("r", function(dat, index, n) {
    var linkItem = links.find(function(link) {
        return link.target == dat.id;
    });
    var radius = 12;
    // linkItem would be undefined if the item was not found in the links
    if (linkItem && linkItem.value > 500) {
        radius = 12;
    } else {
        radius = 6;
    }

    // you should double the radius towards the end,
    // so that radius doesn't get overwritten
    if (dat.level === 0) {
        radius = 2 * radius;
    }

    return radius;
})

Upvotes: 2

Related Questions