D3 Node radius depends on number of links : weight property
14,529
d3.v4 does not support weight property. So I think you will have to calculate the node weight by yourselves. try this way.
node.append("circle")
.attr("r", function(d) {
d.weight = link.filter(function(l) {
return l.source.index == d.index || l.target.index == d.index
}).size();
var minRadius = 10;
return minRadius + (d.weight * 2);
});
In d3.v3, we have weight property and can be used as shown below.
node.append("circle")
.attr("r", function(d) {
var minRadius = 10;
return minRadius + (d.weight * 2);
});
Fiddle Example - https://jsfiddle.net/gilsha/9d6edrte/
Author by
Inchara Raveendra
Updated on August 21, 2022Comments
-
Inchara Raveendra over 1 year
I am trying to create a force directed graph with D3. As for now, the radius of the node depends on a key-value pair in JSON ( d.size )
I'm aware of the d3.weight property which can be used to count the number of links and associate with radius attribute of the circle, but I somehow could not get it to work.
Please help me with this.
Find the code below:
d3.json('graph.json', (error, graph) => { const width = 1200; const height = 900; const simulation = d3.forceSimulation() .nodes(graph.nodes) .force('link', d3.forceLink().id(d => d.id)) .force('charge', d3.forceManyBody().strength([-605])) .force('center', d3.forceCenter(width / 2, height / 2)) .on('tick', ticked); simulation.force('link') .links(graph.links) .distance([140]); const R = 30; const svg = d3.select('body').append('svg') .attr('width', width) .attr('height', height); // add defs-marker // add defs-markers svg.append('svg:defs').selectAll('marker') .data([{ id: 'end-arrow', opacity: 1 }, { id: 'end-arrow-fade', opacity: 0.1 }]) .enter().append('marker') .attr('id', d => d.id) .attr('viewBox', '0 0 10 10') .attr('refX', 2 * R) .attr('refY', 5) .attr('markerWidth', 4) .attr('markerHeight', 4) .attr('orient', 'auto') .append('svg:path') .attr('d', 'M0,0 L0,10 L10,5 z') .style('opacity', d => d.opacity); let link = svg.selectAll('line') .data(graph.links) .enter().append('line'); link .attr('class', 'link') .attr('marker-end', 'url(#end-arrow)') .on('mouseout', fade(1)); let node = svg.selectAll('.node') .data(graph.nodes) .enter().append('g') .attr('class', 'node'); node.append('circle') .attr('r', function (d) { return (d.size * 12); }) .on('mouseover', fade(0.1)) .on('mouseout', fade(1)) .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); node.append('text') .attr('x', 0) .attr('dy', '.35em') .text(d => d.name); function ticked() { link .attr('x1', d => d.source.x) .attr('y1', d => d.source.y) .attr('x2', d => d.target.x) .attr('y2', d => d.target.y); node .attr('transform', d => `translate(${d.x},${d.y})`); } function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } function dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; } const linkedByIndex = {}; graph.links.forEach(d => { linkedByIndex[`${d.source.index},${d.target.index}`] = 1; }); function isConnected(a, b) { return linkedByIndex[`${a.index},${b.index}`] || linkedByIndex[`${b.index},${a.index}`] || a.index === b.index; } function fade(opacity) { return d => { node.style('stroke-opacity', function (o) { const thisOpacity = isConnected(d, o) ? 1 : opacity; this.setAttribute('fill-opacity', thisOpacity); return thisOpacity; }); link.style('stroke-opacity', o => (o.source === d || o.target === d ? 1 : opacity)); link.attr('marker-end', o => (opacity === 1 || o.source === d || o.target === d ? 'url(#end-arrow)' : 'url(#end-arrow-fade)')); }; } })
The JSON structure is as below:
{ "nodes": [ { "name": "A", "id": 0, "size": 1 }, { "name": "D", "id": 1, "size": 2 }, { "name": "K", "id": 2, "size": 3 } ], "links": [ { "source": 0, //id of the soure application "target": 1 //id of the destination application }, { "source": 0, "target": 2 }, { "source": 3, "target": 4 } ] }
-
Gerardo Furtado about 7 years"I'm aware of the d3.weight property which can be used to count the number of links"... well, there is no
d3.weight
in D3 v4.x. -
Inchara Raveendra about 7 years@GerardoFurtado Thank you for that information! It really helped :)
-
-
Inchara Raveendra about 7 yearsThanks for your response. The first solution did not work for me unforunately!
-
Gilsha about 7 yearsI created a fiddle and seems to work fine with the random data. jsfiddle.net/gilsha/n4m1r8nb/214
-
Inchara Raveendra about 7 yearsI have another issue with the code. If there exists a node which is not connected to any other node, it will not appear (slides away from the screen). How do i make those nodes stay in view or maybe float next to the other nodes without an interconnection?
-
Gilsha about 7 yearsShould be a problem with the charge you apply to the force layout. Try adjusting that.
-
Inchara Raveendra about 7 yearsLet us continue this discussion in chat.