[SPARK-56792][SQL] Support pan and zoom for SQL plan visualization#55769
[SPARK-56792][SQL] Support pan and zoom for SQL plan visualization#55769yaooqinn wants to merge 2 commits into
Conversation
### What changes were proposed in this pull request? Add pan and zoom controls to the SQL execution plan visualization rendered on the SQL tab's execution detail page. The SVG that hosts the dagre-d3 plan now lives inside a fixed-height viewport (70vh) and is wrapped in an inner `<g class="zoom-layer">`. A `d3.zoom()` behavior is attached to the SVG and applies its transform to the zoom-layer; the viewBox keeps performing the natural fit. A small floating toolbar in the top-right offers `-` / current % / `+` buttons, and `+` / `-` / `0` keyboard shortcuts work whenever the cursor is over the plan area. Notes: - Pan/zoom is suppressed when the user interacts with HTML labels (`<foreignObject>`) so metric tables in detailed mode remain selectable. - The SVG download is now insulated from the user's current view: the cloned SVG resets the zoom-layer transform and uses the viewBox as its own `width`/`height` so external viewers render at the natural plan size, matching the previous download behavior. - Detailed-mode rerender reuses the same setup so zoom/pan keeps working after toggling "Show metrics in graph nodes". ### Why are the changes needed? Spark plans frequently grow large enough that the previous fit-the-page SVG becomes hard to read: clusters wrap, scroll bars chase the cursor, and zooming the browser distorts the surrounding page. Standard pan/zoom on the plan itself is the conventional way to navigate large DAGs and is a building block for further plan-viz work under SPARK-55760. ### Does this PR introduce _any_ user-facing change? Yes. The SQL tab's plan visualization has a fixed-height viewport with new zoom controls (toolbar + wheel + drag-to-pan + keyboard). ### How was this patch tested? - `build/sbt sql/Test/compile` - `build/sbt sql/scalastyle sql/Test/scalastyle` - `dev/lint-js` on the SQL static resources directory ### Was this patch authored or co-authored using generative AI tooling? Generated-by: GitHub Copilot CLI 1.0.44 with Claude Opus 4.7 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
dongjoon-hyun
left a comment
There was a problem hiding this comment.
Thank you. Could you provide a screenshot, @yaooqinn ?
| var svg = svgArg || planVizContainer().select("svg"); | ||
| if (!svg || svg.empty() || !planVizZoom) return; | ||
| svg.call(planVizZoom.transform, d3.zoomIdentity); | ||
| } |
There was a problem hiding this comment.
Given that d3.zoomIdentity, what is the difference from invoking updateZoomLevelLabel(1) directly instead of fitToViewport?
Is it for simply invoking event to update label somehow?
There was a problem hiding this comment.
You're right, this is overengineered. Pushed 280e7aa9e77 to drop fitToViewport and call updateZoomLevelLabel(1) directly.
setupZoomAndPan is invoked on a freshly created <svg> (both render paths do selectAll("svg").remove() before appending), so:
svg.call(planVizZoom)auto-initializessvgNode.__zoomtod3.zoomIdentity.- The just-appended
zoom-layer<g>has notransformattribute, and the SVG'sviewBoxwith the defaultpreserveAspectRatio="xMidYMid meet"already provides the natural fit.
So svg.call(planVizZoom.transform, d3.zoomIdentity) was firing a zoom event whose only observable effect was setting the toolbar label to 100%. Calling updateZoomLevelLabel(1) directly is equivalent and clearer.
|
@dongjoon-hyun sure, let me run a demo on my laptop, but it could be not that obvious to take a look at the screenshot for an animation |
Recording.2026-05-08.232958.mp4 |
…elLabel Per review feedback: with the fresh SVG that setupZoomAndPan binds to, d3-zoom auto-initializes __zoom to identity on `svg.call(zoom)`, the zoom-layer has no transform attribute, and the SVG viewBox plus the default `preserveAspectRatio="xMidYMid meet"` already provides the natural fit. The previous `fitToViewport` helper therefore just fired a zoom event whose only observable effect was setting the toolbar label to 100%. Replace the call with `updateZoomLevelLabel(1)` directly and remove the helper. Generated-by: GitHub Copilot CLI 1.0.44 with Claude Opus 4.7 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
### What changes were proposed in this pull request? Add pan and zoom controls to the SQL execution plan visualization rendered on the SQL tab's execution detail page. The SVG that hosts the dagre-d3 plan now lives inside a fixed-height viewport (70vh) and is wrapped in an inner `<g class="zoom-layer">`. A `d3.zoom()` behavior is attached to the SVG and applies its transform to the zoom-layer; the viewBox keeps performing the natural fit. A small floating toolbar in the top-right offers `-` / current % / `+` buttons, and `+` / `-` / `0` keyboard shortcuts work whenever the cursor is over the plan area. Notes: - Pan/zoom is suppressed when the user interacts with HTML labels (`<foreignObject>`) so metric tables in detailed mode remain selectable. - The SVG download is now insulated from the user's current view: the cloned SVG resets the zoom-layer transform and uses the viewBox as its own `width`/`height` so external viewers render at the natural plan size, matching the previous download behavior. - Detailed-mode rerender reuses the same setup so zoom/pan keeps working after toggling "Show metrics in graph nodes". ### Why are the changes needed? Spark plans frequently grow large enough that the previous fit-the-page SVG becomes hard to read: clusters wrap, scroll bars chase the cursor, and zooming the browser distorts the surrounding page. Standard pan/zoom on the plan itself is the conventional way to navigate large DAGs and is a building block for further plan-viz work under SPARK-55760. ### Does this PR introduce _any_ user-facing change? Yes. The SQL tab's plan visualization has a fixed-height viewport with new zoom controls (toolbar + wheel + drag-to-pan + keyboard). ### How was this patch tested? - `build/sbt sql/Test/compile` - `build/sbt sql/scalastyle sql/Test/scalastyle` - `dev/lint-js` on the SQL static resources directory ### Was this patch authored or co-authored using generative AI tooling? Generated-by: GitHub Copilot CLI 1.0.44 with Claude Opus 4.7 Closes #55769 from yaooqinn/SPARK-56792. Authored-by: Kent Yao <yao@apache.org> Signed-off-by: Kent Yao <yao@apache.org> (cherry picked from commit ce31445) Signed-off-by: Kent Yao <yao@apache.org>
### What changes were proposed in this pull request? Add pan and zoom controls to the SQL execution plan visualization rendered on the SQL tab's execution detail page. The SVG that hosts the dagre-d3 plan now lives inside a fixed-height viewport (70vh) and is wrapped in an inner `<g class="zoom-layer">`. A `d3.zoom()` behavior is attached to the SVG and applies its transform to the zoom-layer; the viewBox keeps performing the natural fit. A small floating toolbar in the top-right offers `-` / current % / `+` buttons, and `+` / `-` / `0` keyboard shortcuts work whenever the cursor is over the plan area. Notes: - Pan/zoom is suppressed when the user interacts with HTML labels (`<foreignObject>`) so metric tables in detailed mode remain selectable. - The SVG download is now insulated from the user's current view: the cloned SVG resets the zoom-layer transform and uses the viewBox as its own `width`/`height` so external viewers render at the natural plan size, matching the previous download behavior. - Detailed-mode rerender reuses the same setup so zoom/pan keeps working after toggling "Show metrics in graph nodes". ### Why are the changes needed? Spark plans frequently grow large enough that the previous fit-the-page SVG becomes hard to read: clusters wrap, scroll bars chase the cursor, and zooming the browser distorts the surrounding page. Standard pan/zoom on the plan itself is the conventional way to navigate large DAGs and is a building block for further plan-viz work under SPARK-55760. ### Does this PR introduce _any_ user-facing change? Yes. The SQL tab's plan visualization has a fixed-height viewport with new zoom controls (toolbar + wheel + drag-to-pan + keyboard). ### How was this patch tested? - `build/sbt sql/Test/compile` - `build/sbt sql/scalastyle sql/Test/scalastyle` - `dev/lint-js` on the SQL static resources directory ### Was this patch authored or co-authored using generative AI tooling? Generated-by: GitHub Copilot CLI 1.0.44 with Claude Opus 4.7 Closes #55769 from yaooqinn/SPARK-56792. Authored-by: Kent Yao <yao@apache.org> Signed-off-by: Kent Yao <yao@apache.org> (cherry picked from commit ce31445) Signed-off-by: Kent Yao <yao@apache.org>
|
Merge to master/4.x/4.2, thank you @sarutak @dongjoon-hyun |
What changes were proposed in this pull request?
Add pan and zoom controls to the SQL execution plan visualization rendered
on the SQL tab's execution detail page.
The SVG that hosts the dagre-d3 plan now lives inside a fixed-height
viewport (70vh) and is wrapped in an inner
<g class="zoom-layer">.A
d3.zoom()behavior is attached to the SVG and applies its transformto the zoom-layer; the viewBox keeps performing the natural fit. A small
floating toolbar in the top-right offers
-/ current % /+buttons,and
+/-/0keyboard shortcuts work whenever the cursor is overthe plan area.
Notes:
(
<foreignObject>) so metric tables in detailed mode remainselectable.
cloned SVG resets the zoom-layer transform and uses the viewBox as
its own
width/heightso external viewers render at the naturalplan size, matching the previous download behavior.
after toggling "Show metrics in graph nodes".
Why are the changes needed?
Spark plans frequently grow large enough that the previous fit-the-page
SVG becomes hard to read: clusters wrap, scroll bars chase the cursor,
and zooming the browser distorts the surrounding page. Standard
pan/zoom on the plan itself is the conventional way to navigate large
DAGs and is a building block for further plan-viz work under
SPARK-55760.
Does this PR introduce any user-facing change?
Yes. The SQL tab's plan visualization has a fixed-height viewport with
new zoom controls (toolbar + wheel + drag-to-pan + keyboard).
How was this patch tested?
build/sbt sql/Test/compilebuild/sbt sql/scalastyle sql/Test/scalastyledev/lint-json the SQL static resources directoryWas this patch authored or co-authored using generative AI tooling?
Generated-by: GitHub Copilot CLI 1.0.44 with Claude Opus 4.7