Сила направленного графа 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;
})