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.

Пытался найти зацепки, но намеков все равно не было. Любые идеи?


person deathlock    schedule 16.11.2017    source источник
comment
Функция, устанавливающая атрибут r, неверна. Аргументами анонимной функции являются текущие данные (d), текущий индекс (i) и текущая группа (узлы). См. github.com/d3/d3-selection#selection_attr.   -  person RecencyEffect    schedule 16.11.2017


Ответы (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;
})
person RecencyEffect    schedule 16.11.2017