提问人:Syed Usama Amer 提问时间:11/16/2023 更新时间:11/16/2023 访问量:25
如何通过 D3 防止散点图上的点之间重叠并确保点保留在图表内?
How to prevent overlapping between dots on scatter plot via D3 and ensure that dots remain within chart?
问:
问题描述: 我正在 React 组件中使用 D3.js 构建散点图。我的目标是显示一组数据点(节点),而不会使它们相互重叠或溢出到图表边界之外。我正在使用 D3 的力模拟来实现这一点。但是,我遇到了两个问题:
- 这些节点相互重叠。
- 某些节点溢出到图表边界之外。
我的工作基于这个可观察的:https://observablehq.com/@keckelt/collision-free-scatter-plot。
尝试的解决方案: 我使用 D3 的 forceSimulation 和 forceX、forceY 和 forceCollide 来定位节点并防止重叠。但是,这些节点仍然重叠,有些节点甚至溢出图表区域。
设置秤: 这是我设置比例的useEffect钩子:
useEffect(() => {
const [widthAdjusted, heightAdjusted] = getAdjustedWidth(width, height);
const scaleX = scaleLinear()
.domain([Math.min(...data.map(d => d.x)), Math.max(...data.map(d => d.x))])
.nice()
.range([0, widthAdjusted]);
const scaleY = scaleLinear()
.domain([Math.min(...data.map(d => d.y)), Math.max(...data.map(d => d.y))])
.nice()
.range([heightAdjusted, 0]);
setScales({ scaleX, scaleY });
}, [data, width, height]);
力模拟: 另一个 useEffect 钩子中的 D3 力模拟设置:
useEffect(() => {
if (!scales) return;
const transformedData = data.map(d => ({
...d,
x: scales.scaleX(d.x),
y: scales.scaleY(d.y),
}));
const forceSimulation = d3.forceSimulation(transformedData)
.force('x', d3.forceX(d => d.x).strength(0.1))
.force('y', d3.forceY(d => d.y).strength(0.1))
.force('collide', d3.forceCollide().radius(20).strength(1))
.stop();
for (let i = 0; i < 4; i++) {
forceSimulation.tick();
}
const updatedData = forceSimulation.nodes().map(d => ({
...d,
x: scales.scaleX.invert(d.x),
y: scales.scaleY.invert(d.y),
}));
setNodes(updatedData);
}, [data, scales]);
如何调整力模拟和缩放,以确保节点不会重叠并保持在图表边界内?
答: 暂无答案
评论