<!DOCTYPE html>
<html>
<head>
<script src="https://d3js.org/d3.v6.js"></script>
</head>
<body>
<svg height="500" width="500"></svg>
<script>
var svg = d3.select('svg'),
width = +svg.attr('width'),
height = +svg.attr('height');
var data = {
nodes: [
{ id: 'a' },
{ id: 'b' },
{ id: 'c' },
{ id: 'x' },
{ id: 'y' },
{ id: 'z' },
],
links: [
{ source: 'a', target: 'b', distance: 200 },
{ source: 'b', target: 'c', distance: 200 },
{ source: 'c', target: 'a', distance: 200 },
{ source: 'x', target: 'y', distance: 200 },
{ source: 'y', target: 'z', distance: 200 },
{ source: 'z', target: 'x', distance: 200 },
],
};
var simulation = d3
.forceSimulation()
.force(
'link',
d3
.forceLink()
.id((d) => d.id)
.distance(function (d) {
return d.distance;
})
.strength(0.5)
)
.force('charge', d3.forceManyBody())
.force('center', d3.forceCenter(width / 2, height / 2));
var link = svg
.append('g')
.attr('class', 'links')
.selectAll('line')
.data(data.links)
.enter()
.append('line')
.attr('stroke', 'black');
var node = svg
.append('g')
.attr('class', 'nodes')
.selectAll('circle')
.data(data.nodes)
.enter()
.append('circle')
.attr('cx', width / 2)
.attr('cy', height / 2)
.attr('r', 20)
.on('click', function (e, d) {
link.data().forEach(function (l) {
if (l.source.id === d.id || l.target.id === d.id) {
l.distance = 0;
} else {
l.distance = 200;
}
});
// re-bind data
simulation.force('link').links(data.links);
// restart simulation
simulation.alpha(1).restart();
});
simulation.nodes(data.nodes).on('tick', ticked);
simulation.force('link').links(data.links);
function ticked() {
node.attr('cx', (d) => d.x).attr('cy', (d) => d.y);
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);
}
</script>
</body>
</html>