I have a force-directed graph with nodes that vary in size depending on how many links they are connected to.
What I would like to do is the following : Make nodes render conditionally so that those with "d.weight" under 21 append a text element, and those equal or above 21 append a circle element.
Below is my code that does not work. The problem may come from the "test" variable.. Any help is more than welcome
var node = g
.selectAll(".circle-group")
.data(nodes)
.join(enter => {
node = enter.append("g")
.attr("class", "circle-group")
var test = function(d){ link.filter(function(l) {
return l.source.index == d.index || l.target.index == d.index
}).size(); }
//NODE BACKGROUND CIRCLE
node.append("circle")
.attr("class", "background")
.style("fill", "#e7c203")
.attr("r", function(d) {
d.weight = link.filter(function(l) {
return l.source.index == d.index || l.target.index == d.index
}).size();
if(d.weight < 2){return "2px"}
else if(d.weight >= 2 && d.weight < 6){return "5px"}
else if(d.weight >= 6 && d.weight < 21){return "10px"}
else if(d.weight >= 21){return "15px"}
else{return "200px"}
})
//NODE TEXT FOREGROUND
if(test < 21){
node.append("text")
.attr("text-anchor", "middle")
.attr("dominant-baseline", "central")
.text(function(d){return d.id})
.attr("fill", "white")
.attr('stroke', 'white')
.attr('stroke-width', '0.1px')
.attr("y", -7)
.style("font-size", "5px")
//NODE IMAGE FOREGROUND
}else{
node.append("circle")
.attr("class", "foreground")
.style("fill", d => `url(#${d.id})`)
.attr("r", function(d) {
d.weight = link.filter(function(l) {
return l.source.index == d.index || l.target.index == d.index
}).size();
if(d.weight < 2){return "2px"}
else if(d.weight >= 2 && d.weight < 6){return "5px"}
else if(d.weight >= 6 && d.weight < 21){return "10px"}
else if(d.weight >= 21){return "15px"}
else{return "200px"}
})
}
node.attr("stroke", "#e7c203").call(drag(simulation));
})
CodePudding user response:
Ok so I finally figured out on my own.
The trick was to filter the nodes and then append the desired element. In my case, since i wanted to append different elements, I had to filter twice (once per condition)
Here is the fixed code below:
var node = g
.selectAll(".circle-group")
.data(nodes)
.join(enter => {
node = enter.append("g")
.attr("class", "circle-group")
var test = function(d){ link.filter(function(l) {
return l.source.index == d.index || l.target.index == d.index
}).size(); }
//NODE BACKGROUND CIRCLE
node.append("circle")
.attr("class", "background")
.style("fill", "#e7c203")
.attr("r", function(d) {
d.weight = link.filter(function(l) {
return l.source.index == d.index || l.target.index == d.index
}).size();
if(d.weight < 2){return "2px"}
else if(d.weight >= 2 && d.weight < 6){return "5px"}
else if(d.weight >= 6 && d.weight < 21){return "10px"}
else if(d.weight >= 21){return "15px"}
else{return "200px"}
})
//NODE TEXT FOREGROUND
node.filter(function(d){ return d.weight<6 }).append("text")
.attr("text-anchor", "middle")
.attr("dominant-baseline", "central")
.text(function(d){return d.id})
.attr("fill", "white")
.attr('stroke', 'white')
.attr('stroke-width', '0.1px')
.attr("y", -7)
.style("font-size", "5px")
//NODE IMAGE FOREGROUND
node.filter(function(d){ return d.weight>5 }).append("circle")
.attr("class", "foreground")
.style("fill", d => `url(#${d.id})`)
.attr("r", function(d) {
d.weight = link.filter(function(l) {
return l.source.index == d.index || l.target.index == d.index
}).size();
if(d.weight < 2){return "2px"}
else if(d.weight >= 2 && d.weight < 6){return "5px"}
else if(d.weight >= 6 && d.weight < 21){return "10px"}
else if(d.weight >= 21){return "15px"}
else{return "200px"}
})
node.attr("stroke", "#e7c203").call(drag(simulation));
})