This is an automated email from the ASF dual-hosted git repository. zqr10159 pushed a commit to branch 2.0.0 in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
commit 4e969d7bcc743edf471649b97a2c418b083feff2 Author: Logic <[email protected]> AuthorDate: Sun May 31 08:41:19 2026 +0800 fix(web-next): cap topology auto-fit zoom --- .../packages/hertzbeat-ui/src/topology-g6.test.tsx | 9 ++++-- web-next/packages/hertzbeat-ui/src/topology-g6.tsx | 32 ++++++++++++++++------ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/web-next/packages/hertzbeat-ui/src/topology-g6.test.tsx b/web-next/packages/hertzbeat-ui/src/topology-g6.test.tsx index 8e675129e8..04a813fb86 100644 --- a/web-next/packages/hertzbeat-ui/src/topology-g6.test.tsx +++ b/web-next/packages/hertzbeat-ui/src/topology-g6.test.tsx @@ -365,12 +365,17 @@ describe('@hertzbeat/ui topology G6 canvas', () => { expect(source).not.toContain("fitAndCenterG6Viewport(runtimeGraph, { when: 'always' }, false)"); expect(source).not.toContain("fitAndCenterG6Viewport(runtimeGraph, { when: 'always' }, { duration: 120 })"); expect(source).not.toContain("runtimeGraph.fitView?.({ when: 'always' }, false);\n await runtimeGraph.fitCenter?.(false);"); - expect(html).toContain('data-hz-topology-g6-auto-fit-zoom-bounds="0.18-1.35"'); - expect(html).toContain('data-hz-topology-g6-auto-fit-max-zoom="1.35"'); + expect(html).toContain('data-hz-topology-g6-auto-fit-zoom-bounds="0.18-1"'); + expect(html).toContain('data-hz-topology-g6-auto-fit-max-zoom="1"'); expect(html).toContain('data-hz-topology-g6-auto-fit-growth="no-magnify-small-graphs"'); + expect(html).toContain('data-hz-topology-g6-auto-fit-zoom-range-owner="hertzbeat-ui-g6-auto-fit-zoom-range"'); + expect(html).toContain('data-hz-topology-g6-operator-zoom-bounds="0.18-4.8"'); expect(html).toContain('data-hz-topology-g6-fit-mode="overflow-only-center"'); expect(clampHzTopologyG6AutoFitZoom(4.8)).toBe(HZ_TOPOLOGY_G6_AUTO_FIT_MAX_ZOOM); expect(clampHzTopologyG6AutoFitZoom(0.72)).toBe(0.72); + expect(source).toContain('withG6AutoFitZoomRange(runtimeGraph, async () => {'); + expect(source).toContain('runtimeGraph.setZoomRange?.([HZ_TOPOLOGY_G6_MIN_ZOOM, HZ_TOPOLOGY_G6_AUTO_FIT_MAX_ZOOM])'); + expect(source).toContain('runtimeGraph.setZoomRange?.([HZ_TOPOLOGY_G6_MIN_ZOOM, HZ_TOPOLOGY_G6_MAX_ZOOM])'); }); it('centers the shared G6 canvas after fit and reset view actions', () => { diff --git a/web-next/packages/hertzbeat-ui/src/topology-g6.tsx b/web-next/packages/hertzbeat-ui/src/topology-g6.tsx index b590d2c5e1..d638b35501 100644 --- a/web-next/packages/hertzbeat-ui/src/topology-g6.tsx +++ b/web-next/packages/hertzbeat-ui/src/topology-g6.tsx @@ -222,6 +222,8 @@ type G6GraphRuntime = { fitCenter?: (animation?: Record<string, unknown> | boolean) => Promise<void>; zoomBy?: (scale: number, animation?: Record<string, unknown> | boolean) => Promise<void>; zoomTo?: (scale: number, animation?: Record<string, unknown> | boolean, origin?: number[]) => Promise<void>; + setZoomRange?: (zoomRange: [number, number]) => void; + getZoomRange?: () => [number, number]; getZoom?: () => number; getPosition?: () => number[]; translateTo?: (position: number[], animation?: Record<string, unknown> | boolean) => Promise<void>; @@ -232,7 +234,7 @@ type G6GraphRuntime = { export const HZ_TOPOLOGY_G6_MIN_ZOOM = 0.18; export const HZ_TOPOLOGY_G6_MAX_ZOOM = 4.8; -export const HZ_TOPOLOGY_G6_AUTO_FIT_MAX_ZOOM = 1.35; +export const HZ_TOPOLOGY_G6_AUTO_FIT_MAX_ZOOM = 1; type HzTopologyG6ViewportSnapshot = { zoom: number; @@ -1128,13 +1130,24 @@ async function fitAndCenterG6Viewport( animation: Record<string, unknown> | boolean ) { if (!runtimeGraph) return; - await runtimeGraph.fitView?.(fitOptions, animation); - await runtimeGraph.fitCenter?.(animation); - const currentZoom = runtimeGraph.getZoom?.(); - const clampedZoom = clampHzTopologyG6AutoFitZoom(currentZoom); - if (clampedZoom !== undefined && currentZoom !== undefined && clampedZoom < currentZoom) { - await runtimeGraph.zoomTo?.(clampedZoom, false); - await runtimeGraph.fitCenter?.(false); + await withG6AutoFitZoomRange(runtimeGraph, async () => { + await runtimeGraph.fitView?.(fitOptions, animation); + await runtimeGraph.fitCenter?.(animation); + const currentZoom = runtimeGraph.getZoom?.(); + const clampedZoom = clampHzTopologyG6AutoFitZoom(currentZoom); + if (clampedZoom !== undefined && currentZoom !== undefined && clampedZoom < currentZoom) { + await runtimeGraph.zoomTo?.(clampedZoom, false); + await runtimeGraph.fitCenter?.(false); + } + }); +} + +async function withG6AutoFitZoomRange(runtimeGraph: G6GraphRuntime, action: () => Promise<void>) { + runtimeGraph.setZoomRange?.([HZ_TOPOLOGY_G6_MIN_ZOOM, HZ_TOPOLOGY_G6_AUTO_FIT_MAX_ZOOM]); + try { + await action(); + } finally { + runtimeGraph.setZoomRange?.([HZ_TOPOLOGY_G6_MIN_ZOOM, HZ_TOPOLOGY_G6_MAX_ZOOM]); } } @@ -1531,6 +1544,7 @@ export function HzTopologyG6Canvas({ width, height: graphHeight, autoFit: false, + zoomRange: [HZ_TOPOLOGY_G6_MIN_ZOOM, HZ_TOPOLOGY_G6_MAX_ZOOM], background: '#08090c', animation: false, data: initialGraphData, @@ -1831,6 +1845,8 @@ export function HzTopologyG6Canvas({ data-hz-topology-g6-auto-fit-zoom-bounds={`${HZ_TOPOLOGY_G6_MIN_ZOOM}-${HZ_TOPOLOGY_G6_AUTO_FIT_MAX_ZOOM}`} data-hz-topology-g6-auto-fit-max-zoom={HZ_TOPOLOGY_G6_AUTO_FIT_MAX_ZOOM} data-hz-topology-g6-auto-fit-growth="no-magnify-small-graphs" + data-hz-topology-g6-auto-fit-zoom-range-owner="hertzbeat-ui-g6-auto-fit-zoom-range" + data-hz-topology-g6-operator-zoom-bounds={`${HZ_TOPOLOGY_G6_MIN_ZOOM}-${HZ_TOPOLOGY_G6_MAX_ZOOM}`} data-hz-topology-g6-fit-mode="overflow-only-center" data-hz-topology-g6-viewport-interaction-state={viewportInteractionState} data-hz-topology-g6-viewport-interaction-owner="hertzbeat-ui-g6-viewport-interaction" --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
