Describe the bug
When zooming in or out, orthogonal edges with user-authored waypoints jump around — flickering between the correct route and a diagonal depending on the exact zoom level.
To Reproduce
- Insert a source vertex at
(870, 430) size (310, 70) — no exitX/exitY (floating port).
- Insert a target vertex at
(450, 250) size (410, 80) — no entryX/entryY.
- Insert an edge between them with waypoints
[(1025, 390), (655, 390)].
graph.getView().setScale(0.75); graph.getView().revalidate();
- Read
state.absolutePoints for the edge. (we expect 4 non-null points (S-route) but see 2 points (diagonal).
Also reproduces at scale = 0.8. Routes correctly at scale ∈ {0.5, 1.0, 1.5, 2.0}.
segment-bug-repro.html
Expected behavior
The route should not change shape as view.scale changes. Zoom should not alter the logical geometry.
Screenshots
Environment
maxGraph version or commit: @maxgraph/core@0.22.0 and current main.
- Desktop or mobile: Desktop.
- OS and version: macOS 26.3.1.
- Browser and version: Chrome 147.
- Node/npm version: Node 20.19.5, npm 10.8.2.
- Used frameworks: N/A.
Additional context
Analysis. Looking at Segment.ts, the "remove bends inside source/target terminal" cleanup (L281-299) compares result points (VIEW coords after pushPoint scales them at L65-66) against source / target (MODEL coords after scaleCellState divides by scale at L54-55). At fractional scale the spaces diverge, and a legitimate VIEW-space waypoint can land inside the MODEL-space terminal bounds — the cleanup then splices it out and the route collapses. Only seems to fire on edges with floating ports.
A patch that fixes it in my testing — comparing against the sourceScaled / targetScaled function parameters (VIEW coords, same space as result):
- if (pts[0] == null && source != null) {
+ if (pts[0] == null && sourceScaled != null) {
while (
result.length > 1 &&
result[1] != null &&
- contains(source, result[1].x, result[1].y)
+ contains(sourceScaled, result[1].x, result[1].y)
) { result.splice(1, 1); }
}
- if (pts[lastInx] == null && target != null) {
+ if (pts[lastInx] == null && targetScaled != null) {
while (
result.length > 1 &&
result[result.length - 1] != null &&
- contains(target, result[result.length - 1].x, result[result.length - 1].y)
+ contains(targetScaled, result[result.length - 1].x, result[result.length - 1].y)
) { result.splice(result.length - 1, 1); }
}
Drawio comparison. The identical code is in jgraph/drawio's internal mxGraph fork, unpatched — but drawio quantises every zoom path to 1% increments or coarser with a source comment citing "rounding errors for zoom steps" as the motivation. @maxgraph/core has no equivalent app-layer mitigation, so the bug is reachable through the default zoomIn button alone (which walks through 1.44, 1.73, 2.08, … at zoomFactor = 1.2).
Scope. OrthConnector and ManhattanConnector both delegate to SegmentConnector, so this affects segmentEdgeStyle, orthogonalEdgeStyle, and manhattanEdgeStyle.
Describe the bug
When zooming in or out, orthogonal edges with user-authored waypoints jump around — flickering between the correct route and a diagonal depending on the exact zoom level.
To Reproduce
(870, 430)size(310, 70)— noexitX/exitY(floating port).(450, 250)size(410, 80)— noentryX/entryY.[(1025, 390), (655, 390)].graph.getView().setScale(0.75); graph.getView().revalidate();state.absolutePointsfor the edge. (we expect 4 non-null points (S-route) but see 2 points (diagonal).Also reproduces at
scale = 0.8. Routes correctly atscale ∈ {0.5, 1.0, 1.5, 2.0}.segment-bug-repro.html
Expected behavior
The route should not change shape as
view.scalechanges. Zoom should not alter the logical geometry.Screenshots
Environment
maxGraphversion or commit:@maxgraph/core@0.22.0and currentmain.Additional context
Analysis. Looking at
Segment.ts, the "remove bends inside source/target terminal" cleanup (L281-299) comparesresultpoints (VIEW coords afterpushPointscales them at L65-66) againstsource/target(MODEL coords afterscaleCellStatedivides by scale at L54-55). At fractional scale the spaces diverge, and a legitimate VIEW-space waypoint can land inside the MODEL-space terminal bounds — the cleanup then splices it out and the route collapses. Only seems to fire on edges with floating ports.A patch that fixes it in my testing — comparing against the
sourceScaled/targetScaledfunction parameters (VIEW coords, same space asresult):Drawio comparison. The identical code is in
jgraph/drawio's internalmxGraphfork, unpatched — but drawio quantises every zoom path to 1% increments or coarser with a source comment citing "rounding errors for zoom steps" as the motivation.@maxgraph/corehas no equivalent app-layer mitigation, so the bug is reachable through the defaultzoomInbutton alone (which walks through1.44, 1.73, 2.08, …atzoomFactor = 1.2).Scope.
OrthConnectorandManhattanConnectorboth delegate toSegmentConnector, so this affectssegmentEdgeStyle,orthogonalEdgeStyle, andmanhattanEdgeStyle.