aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/graph/DotGraphVisualizer.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/frontend/src/graph/DotGraphVisualizer.tsx')
-rw-r--r--subprojects/frontend/src/graph/DotGraphVisualizer.tsx53
1 files changed, 34 insertions, 19 deletions
diff --git a/subprojects/frontend/src/graph/DotGraphVisualizer.tsx b/subprojects/frontend/src/graph/DotGraphVisualizer.tsx
index 02f31085..eec72a7d 100644
--- a/subprojects/frontend/src/graph/DotGraphVisualizer.tsx
+++ b/subprojects/frontend/src/graph/DotGraphVisualizer.tsx
@@ -9,7 +9,7 @@ import { type Graphviz, graphviz } from 'd3-graphviz';
9import type { BaseType, Selection } from 'd3-selection'; 9import type { BaseType, Selection } from 'd3-selection';
10import { reaction, type IReactionDisposer } from 'mobx'; 10import { reaction, type IReactionDisposer } from 'mobx';
11import { observer } from 'mobx-react-lite'; 11import { observer } from 'mobx-react-lite';
12import { useCallback, useRef } from 'react'; 12import { useCallback, useRef, useState } from 'react';
13 13
14import getLogger from '../utils/getLogger'; 14import getLogger from '../utils/getLogger';
15 15
@@ -44,6 +44,7 @@ function DotGraphVisualizer({
44 const graphvizRef = useRef< 44 const graphvizRef = useRef<
45 Graphviz<BaseType, unknown, null, undefined> | undefined 45 Graphviz<BaseType, unknown, null, undefined> | undefined
46 >(); 46 >();
47 const [animate, setAnimate] = useState(true);
47 48
48 const setElement = useCallback( 49 const setElement = useCallback(
49 (element: HTMLDivElement | null) => { 50 (element: HTMLDivElement | null) => {
@@ -72,15 +73,20 @@ function DotGraphVisualizer({
72 renderer.tweenPrecision('5%'); 73 renderer.tweenPrecision('5%');
73 renderer.tweenShapes(false); 74 renderer.tweenShapes(false);
74 renderer.convertEqualSidedPolygons(false); 75 renderer.convertEqualSidedPolygons(false);
75 const transition = () => 76 if (animate) {
76 d3.transition().duration(transitionTimeOrDefault).ease(d3.easeCubic); 77 const transition = () =>
77 /* eslint-disable-next-line @typescript-eslint/no-unsafe-argument, 78 d3
78 @typescript-eslint/no-explicit-any -- 79 .transition()
79 Workaround for error in `@types/d3-graphviz`. 80 .duration(transitionTimeOrDefault)
80 */ 81 .ease(d3.easeCubic);
81 renderer.transition(transition as any); 82 /* eslint-disable-next-line @typescript-eslint/no-unsafe-argument,
82 let animate = true; 83 @typescript-eslint/no-explicit-any --
83 let previousSize = 0; 84 Workaround for error in `@types/d3-graphviz`.
85 */
86 renderer.transition(transition as any);
87 } else {
88 renderer.tweenPaths(false);
89 }
84 let newViewBox = { width: 0, height: 0 }; 90 let newViewBox = { width: 0, height: 0 };
85 renderer.onerror(LOG.error.bind(LOG)); 91 renderer.onerror(LOG.error.bind(LOG));
86 renderer.on( 92 renderer.on(
@@ -108,7 +114,11 @@ function DotGraphVisualizer({
108 d3.select(element).selectAll('title').remove(); 114 d3.select(element).selectAll('title').remove();
109 }); 115 });
110 if (fitZoom !== undefined) { 116 if (fitZoom !== undefined) {
111 renderer.on('transitionStart', () => fitZoom(newViewBox)); 117 if (animate) {
118 renderer.on('transitionStart', () => fitZoom(newViewBox));
119 } else {
120 renderer.on('end', () => fitZoom(false));
121 }
112 } 122 }
113 disposerRef.current = reaction( 123 disposerRef.current = reaction(
114 () => dotSource(graph), 124 () => dotSource(graph),
@@ -119,20 +129,25 @@ function DotGraphVisualizer({
119 const [source, size] = result; 129 const [source, size] = result;
120 // Disable tweening for large graphs to improve performance. 130 // Disable tweening for large graphs to improve performance.
121 // See https://github.com/magjac/d3-graphviz/issues/232#issuecomment-1157555213 131 // See https://github.com/magjac/d3-graphviz/issues/232#issuecomment-1157555213
122 const newAnimate = size + previousSize < animateThresholdOrDefault; 132 const newAnimate = size < animateThresholdOrDefault;
123 if (animate !== newAnimate) { 133 if (animate === newAnimate) {
124 renderer.tweenPaths(newAnimate); 134 renderer.renderDot(source);
125 animate = newAnimate; 135 } else {
136 setAnimate(newAnimate);
126 } 137 }
127 previousSize = size;
128 renderer.renderDot(source);
129 }, 138 },
130 { fireImmediately: true }, 139 { fireImmediately: true },
131 ); 140 );
132 graphvizRef.current = renderer; 141 graphvizRef.current = renderer;
133 } 142 }
134 }, 143 },
135 [graph, fitZoom, transitionTimeOrDefault, animateThresholdOrDefault], 144 [
145 graph,
146 fitZoom,
147 transitionTimeOrDefault,
148 animateThresholdOrDefault,
149 animate,
150 ],
136 ); 151 );
137 152
138 return <GraphTheme ref={setElement} />; 153 return <GraphTheme ref={setElement} />;
@@ -141,7 +156,7 @@ function DotGraphVisualizer({
141DotGraphVisualizer.defaultProps = { 156DotGraphVisualizer.defaultProps = {
142 fitZoom: undefined, 157 fitZoom: undefined,
143 transitionTime: 250, 158 transitionTime: 250,
144 animateThreshold: 50, 159 animateThreshold: 100,
145}; 160};
146 161
147export default observer(DotGraphVisualizer); 162export default observer(DotGraphVisualizer);