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]

Reply via email to