feat: smaller subpaths in endpoint graph
This commit is contained in:
@@ -24,8 +24,24 @@ function renderGraph(containerSelector, graph, options = {}) {
|
||||
const nodes = graph.nodes.map(d => Object.assign({}, d));
|
||||
const endpoints = Array.isArray(graph.endpoints) ? graph.endpoints : [];
|
||||
|
||||
// Identify leaf nodes (last segment of endpoints) vs intermediate nodes
|
||||
const leafNodeIds = new Set();
|
||||
endpoints.forEach(ep => {
|
||||
const path = ep.path || '';
|
||||
const segments = path.split('/').filter(Boolean);
|
||||
if (segments.length > 0) {
|
||||
const lastSegment = segments[segments.length - 1];
|
||||
leafNodeIds.add(lastSegment);
|
||||
}
|
||||
});
|
||||
|
||||
// Assign radius based on whether node is a leaf or intermediate
|
||||
nodes.forEach(node => {
|
||||
node.isLeaf = leafNodeIds.has(node.id);
|
||||
node.radius = node.isLeaf ? 22 : 14; // Bigger for endpoints, smaller for sub-paths
|
||||
});
|
||||
|
||||
// Visual constants
|
||||
const nodeRadius = 16;
|
||||
const labelOffset = 12; // below the circle
|
||||
|
||||
// Compute left-to-right depth strictly from path segment indices
|
||||
@@ -55,12 +71,12 @@ function renderGraph(containerSelector, graph, options = {}) {
|
||||
.attr('class', 'node');
|
||||
|
||||
node.append('circle')
|
||||
.attr('r', nodeRadius)
|
||||
.attr('r', d => d.radius || 14)
|
||||
.call(drag(simulation()));
|
||||
|
||||
node.append('text')
|
||||
.attr('x', 0)
|
||||
.attr('y', nodeRadius + labelOffset)
|
||||
.attr('y', d => (d.radius || 14) + labelOffset)
|
||||
.attr('text-anchor', 'middle')
|
||||
.text(d => d.id);
|
||||
|
||||
@@ -120,11 +136,13 @@ function renderGraph(containerSelector, graph, options = {}) {
|
||||
|
||||
function ticked() {
|
||||
// Clamp nodes vertically to avoid drifting too far down/up
|
||||
const minY = paddingY + nodeRadius;
|
||||
const maxY = height - paddingY - nodeRadius - labelOffset - 2;
|
||||
// Use the maximum radius to ensure all nodes stay within bounds
|
||||
const maxRadius = Math.max(...nodes.map(n => n.radius || 14));
|
||||
const minY = paddingY + maxRadius;
|
||||
const maxY = height - paddingY - maxRadius - labelOffset - 2;
|
||||
|
||||
// Push nodes away from links they don't belong to
|
||||
const minDistFromLink = nodeRadius + 8; // minimum distance from unrelated links
|
||||
const minDistFromLink = maxRadius + 8; // minimum distance from unrelated links
|
||||
for (const n of nodes) {
|
||||
const connectedLinks = nodeLinks.get(n.id) || new Set();
|
||||
for (const l of links) {
|
||||
@@ -175,7 +193,7 @@ function renderGraph(containerSelector, graph, options = {}) {
|
||||
.velocityDecay(0.35)
|
||||
.force('link', d3.forceLink().id(d => d.id).distance(40).strength(1.1).iterations(2))
|
||||
.force('charge', d3.forceManyBody().strength(-420))
|
||||
.force('collision', d3.forceCollide().radius(nodeRadius + 50).strength(0.96))
|
||||
.force('collision', d3.forceCollide().radius(d => (d.radius || 14) + 50).strength(0.96))
|
||||
.force('x', fx)
|
||||
.force('y', fy);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user