我试图在d3中的有力布局图中选择一组节点,然后压缩节点表单的组件。我的想法是进行力模拟,如下所示:
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().distance(function(d) {
return d.distance;
}).strength(0.5))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));由于它依赖于距离,所以我想在图形的数据中查找和选择适当的链接并缩小它,例如
graph_data.links[indx].distance = 0;会压缩它。当我考虑这个问题时,我需要用新的数据以某种方式刷新图表。但是,这并不理想,因为每次选择组件时,我都不希望图形重新构建自己。是否有一种方法可以改变这些距离,而不需要重新绘制新修改的数据,例如直接选择模拟图中的链接,而不是传递的数据?
发布于 2021-01-01 00:20:32
但是,这并不理想,因为每次选择组件时,我都不希望图形重新构建自己。
你真的不必,只需更新数据并重新启动模拟:
<!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>
https://stackoverflow.com/questions/65524929
复制相似问题