Сила направленного графа d3.js: Как сделать так, чтобы размер узла зависел от значения ссылок?

У меня есть такие данные:

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 //
]

Я пытался установить размер радиуса узлов в соответствии с value из ссылок, которые указали узел в качестве его target,

Так, например, узел B должен иметь свой размер в соответствии со значением 276 (ссылка, в которой целью является узел B).

Это то, что я использую:

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)

Это, кажется, не работает, хотя. Говорит, что не распознает link.filterчто-то я взял отсюда. Я использую d3.js v4.

Пробовал искать подсказки, но до сих пор не получил намеков. Есть идеи?

1 ответ

Решение

Есть несколько вещей, которые нужно изменить, но сначала вы должны понимать, что вы не добавляете автоматически links к данным узла.

Таким образом, цель оператора фильтра состоит в том, чтобы найти соответствующую ссылку в этом массиве на основе индекса. Здесь нет link переменная передается во внешнюю функцию, но вместо этого вы должны искать через links массив, определенный выше для одной ссылки, которая имеет цель с идентификатором узла.

Если вам нужна только одна ссылка, а не все, используйте Array.prototype.find. Но filter а также find работают одинаково - определенная анонимная функция вызывается для каждого элемента в массиве. find останавливается на первом найденном объекте, а filter возвращает все совпадения.

.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;
})
Другие вопросы по тегам