Improve parallel edge label staggering with bidirectional support

- Increase label stagger to 12% of curve (from 10%)
- Reverse stagger direction for opposite-direction edges
- Labels now distribute evenly on both sides of center
- Remove clamping to allow fuller curve utilization

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Jan-Henrik 2026-02-05 14:26:47 +01:00
parent ce7f6c2eed
commit f797da9835

View file

@ -96,25 +96,34 @@ const CustomEdge = ({
// Create cubic bezier path using custom control points // Create cubic bezier path using custom control points
const edgePath = `M ${params.sx},${params.sy} C ${params.sourceControlX},${params.sourceControlY} ${params.targetControlX},${params.targetControlY} ${params.tx},${params.ty}`; const edgePath = `M ${params.sx},${params.sy} C ${params.sourceControlX},${params.sourceControlY} ${params.targetControlX},${params.targetControlY} ${params.tx},${params.ty}`;
// Smart label positioning: vary position along curve based on offset // Calculate label position along the curve with staggering for parallel edges
// This staggers labels for parallel edges to reduce overlap // Use t parameter variation (position along curve from 0 to 1)
// Symmetric staggering: negative offsets toward source, positive toward target // Center edge at t=0.5, others staggered symmetrically
const labelPositionOffset = offsetMultiplier * 0.1; // 10% stagger per offset unit // Reverse stagger direction for edges going opposite to normalized direction
const t = 0.5 + labelPositionOffset; let tStagger = offsetMultiplier * 0.12; // 12% of curve per offset unit
// Clamp t to reasonable range to keep labels on the visible part of the curve // Check if this edge goes in the reverse direction relative to normalized group
const clampedT = Math.max(0.3, Math.min(0.7, t)); if (parallelGroupKey) {
const [normalizedSource, normalizedTarget] = parallelGroupKey.split('<->');
const isReversed = source === normalizedTarget && target === normalizedSource;
if (isReversed) {
tStagger = -tStagger; // Reverse the stagger direction
}
}
const t = 0.5 + tStagger;
// Calculate position on Bezier curve at parameter t
const labelX = const labelX =
Math.pow(1 - clampedT, 3) * params.sx + Math.pow(1 - t, 3) * params.sx +
3 * Math.pow(1 - clampedT, 2) * clampedT * params.sourceControlX + 3 * Math.pow(1 - t, 2) * t * params.sourceControlX +
3 * (1 - clampedT) * Math.pow(clampedT, 2) * params.targetControlX + 3 * (1 - t) * Math.pow(t, 2) * params.targetControlX +
Math.pow(clampedT, 3) * params.tx; Math.pow(t, 3) * params.tx;
const labelY = const labelY =
Math.pow(1 - clampedT, 3) * params.sy + Math.pow(1 - t, 3) * params.sy +
3 * Math.pow(1 - clampedT, 2) * clampedT * params.sourceControlY + 3 * Math.pow(1 - t, 2) * t * params.sourceControlY +
3 * (1 - clampedT) * Math.pow(clampedT, 2) * params.targetControlY + 3 * (1 - t) * Math.pow(t, 2) * params.targetControlY +
Math.pow(clampedT, 3) * params.ty; Math.pow(t, 3) * params.ty;
return { edgePath, labelX, labelY }; return { edgePath, labelX, labelY };
}, [sourceNode, targetNode, sourceShape, targetShape, sourceX, sourceY, targetX, targetY, data]); }, [sourceNode, targetNode, sourceShape, targetShape, sourceX, sourceY, targetX, targetY, data]);