fix(behavior): restore node zIndex after drag-element ends#7636
Conversation
drag-element calls graph.frontElement() on drag start, which elevates the node's zIndex to max(all) + 1. This value persisted after drag end, causing hover-activate to compute edge zIndex higher than non-neighbor nodes, rendering edges on top of unrelated nodes. - Store original zIndex values before frontElement() in onDragStart - Restore them via setElementZIndex() in onDragEnd - Add unit test verifying zIndex restoration after drag cycle
There was a problem hiding this comment.
Code Review
This pull request introduces a mechanism to store and restore the zIndex of elements during drag operations in G6, ensuring that elements return to their original rendering layer after being brought to the front. While the implementation includes new tests and logic to handle target elements, the review feedback correctly identifies a significant limitation: the current approach only captures the zIndex of immediate targets and fails to account for the recursive zIndex adjustments made to combos and their descendants, which will likely result in persistent rendering issues for hierarchical structures.
| private storeOriginalZIndices(ids: ID[]) { | ||
| const { graph } = this.context; | ||
| this.originalZIndices = {}; | ||
| ids.forEach((id) => { | ||
| this.originalZIndices[id] = graph.getElementZIndex(id); | ||
| }); | ||
| } |
There was a problem hiding this comment.
The storeOriginalZIndices method currently only captures the zIndex of the immediate elements being dragged (this.target). However, graph.frontElement (called on line 276) has significant side effects when a combo is involved: it recursively elevates the zIndex of the entire hierarchy, including the top-level ancestor, all descendants, and internal edges (as seen in graph.ts lines 1763-1775).
Because these related elements are not captured here, their elevated zIndex will persist after the drag ends. This means the rendering issue described in the PR (edges appearing on top of other nodes) will still occur for any nodes or edges within a dragged combo's subtree. You should ensure that all elements modified by frontElement have their original zIndex stored and restored.
Summary
drag-element.onDragStartcallsgraph.frontElement(target), which sets the dragged node'szIndextomax(all_elements) + 1. This elevated zIndex persists after drag ends - there is no reset.When
hover-activatelater fires on the same node,computeZIndexrecalculates edge zIndex asMath.max(source.zIndex, target.zIndex) - 1. Because the dragged node's zIndex is now elevated, its edges get a zIndex higher than non-neighbor nodes (still at 0), causing edges to render on top of unrelated nodes.The problem compounds: each subsequent drag of any node further escalates the global max zIndex.
Fix
frontElement()inonDragStartsetElementZIndex()inonDragEndfrontElement()is still called during drag so the dragged node renders above others while draggingReproduction
JSFiddle: https://jsfiddle.net/z03jrefa/5/
Snapshot tests
Some snapshot tests will need regeneration — they previously captured the buggy elevated zIndex state after drag-end. The new snapshots reflect the corrected behavior.
Test plan
getElementZIndex()returns original value after drag cycledrag-element,z-index,bubble-sets,hull,click-select-drag-node,element-combo-drag,drag-element-combo)