diff --git a/packages/ott-vis-panel/src/chartutils.ts b/packages/ott-vis-panel/src/chartutils.ts new file mode 100644 index 000000000..72299959c --- /dev/null +++ b/packages/ott-vis-panel/src/chartutils.ts @@ -0,0 +1,28 @@ +import { useEffect, useState } from "react"; +import * as d3 from "d3"; + +export function useD3Zoom(svgRef: React.MutableRefObject) { + const [chartTransform, setChartTransform] = useState("translate(0, 0)"); + // run this only once after the first render + useEffect(() => { + if (!svgRef.current) { + return; + } + const svg = d3.select(svgRef.current); + svg.select("g.chart").attr("transform", chartTransform); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + if (!svgRef.current) { + return; + } + const svg = d3.select(svgRef.current); + const zoom = d3.zoom().on("zoom", handleZoom); + function handleZoom(e: any) { + svg.select("g.chart").attr("transform", e.transform); + setChartTransform(e.transform); + } + svg.call(zoom); + }, [svgRef, chartTransform]); +} diff --git a/packages/ott-vis-panel/src/components/TreeDisplay.tsx b/packages/ott-vis-panel/src/components/TreeDisplay.tsx index d5f39b69c..7381ca658 100644 --- a/packages/ott-vis-panel/src/components/TreeDisplay.tsx +++ b/packages/ott-vis-panel/src/components/TreeDisplay.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useRef, useState } from "react"; +import React, { useCallback, useEffect, useRef } from "react"; import * as d3 from "d3"; import type { SystemState } from "ott-vis/types"; import { useEventBus } from "eventbus"; @@ -11,6 +11,7 @@ import { type TreeNode, buildMonolithTrees, } from "treeutils"; +import { useD3Zoom } from "chartutils"; interface TreeDisplayProps extends TreeDisplayStyleProps { systemState: SystemState; @@ -151,8 +152,6 @@ const TreeDisplay: React.FC = ({ (a, b) => d3.ascending(a.region, b.region) || d3.ascending(a.id, b.id) ); - const [chartTransform, setChartTransform] = useState("translate(0, 0)"); - const getRadius = useCallback( (group: string): number => { if (group === "client") { @@ -506,13 +505,6 @@ const TreeDisplay: React.FC = ({ .transition(tr) .attr("d", diagonal) .attr("stroke-width", 1.5); - - const zoom = d3.zoom().on("zoom", handleZoom); - function handleZoom(e: any) { - svg.select("g.chart").attr("transform", e.transform); - setChartTransform(e.transform); - } - svg.call(zoom); } }, [ systemState, @@ -527,15 +519,7 @@ const TreeDisplay: React.FC = ({ horizontal, ]); - // run this only once after the first render - useEffect(() => { - if (!svgRef.current) { - return; - } - const svg = d3.select(svgRef.current); - svg.select("g.chart").attr("transform", chartTransform); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + useD3Zoom(svgRef); const eventBus = useEventBus(); useEffect(() => { diff --git a/packages/ott-vis-panel/src/components/views/TopologyView.tsx b/packages/ott-vis-panel/src/components/views/TopologyView.tsx index 7a36a9f73..f4bda4f4b 100644 --- a/packages/ott-vis-panel/src/components/views/TopologyView.tsx +++ b/packages/ott-vis-panel/src/components/views/TopologyView.tsx @@ -12,6 +12,7 @@ import { } from "treeutils"; import "./topology-view.css"; import { useColorProvider } from "colors"; +import { useD3Zoom } from "chartutils"; /** * The goal of this component is to show a more accurate topology view from the perspective of actual network connections. @@ -174,6 +175,8 @@ export const TopologyView: React.FC = ({ systemState, width, renderTrees(monolithSubtrees, ".monolith-trees"); }, [svgRef, monolithTrees, balancerTrees, subtreePadding, nodeRadius, colors]); + useD3Zoom(svgRef); + return (