Skip to content

Commit a1336db

Browse files
authored
ott-vis-panel: improve performance by letting react render svg elements (#1430)
1 parent 7408096 commit a1336db

File tree

1 file changed

+32
-36
lines changed

1 file changed

+32
-36
lines changed

packages/ott-vis-panel/src/components/ForceGraph.tsx

+32-36
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,8 @@ const ForceGraph: React.FC<ForceGraphProps> = ({
4040
// Specify the color scale.
4141
const color = d3.scaleOrdinal(d3.schemeCategory10);
4242

43-
// The force simulation mutates links and nodes, so create a copy
44-
// so that re-evaluating this cell produces the same result.
45-
const links: Link[] = data.links.map((d: Link) => ({ ...d }));
46-
const nodes: Node[] = data.nodes.map((d: Node) => ({ ...d }));
43+
const links: Link[] = data.links;
44+
const nodes: Node[] = data.nodes;
4745

4846
// Create a simulation with several forces.
4947
const simulation = d3
@@ -84,35 +82,14 @@ const ForceGraph: React.FC<ForceGraphProps> = ({
8482
);
8583

8684
useEffect(() => {
87-
const svg = d3
88-
.select(svgRef.current)
89-
.attr("width", width)
90-
.attr("height", height)
91-
.attr("viewBox", [-width / 2, -height / 2, width, height])
92-
.attr("style", "max-width: 100%; height: auto;");
93-
svg.selectAll("*").remove();
85+
const svg = d3.select(svgRef.current).attr("style", "max-width: 100%; height: auto;");
9486

9587
// Add a line for each link, and a circle for each node.
96-
const link = svg
97-
.append("g")
98-
.attr("stroke", "#999")
99-
.attr("stroke-opacity", 0.6)
100-
.selectAll("line")
101-
.data(links)
102-
.join("line")
103-
.attr("stroke-width", d => Math.sqrt(d.value));
104-
105-
const node = svg
106-
.append("g")
107-
.attr("stroke", "#fff")
108-
.attr("stroke-width", 1.5)
109-
.selectAll("circle")
110-
.data(nodes)
111-
.join("circle")
112-
.attr("r", d => radius(d.radius))
113-
.attr("fill", d => color(d.group));
114-
115-
node.append("title").text(d => d.id);
88+
const link = svg.select("g.links").selectAll("line").data(links);
89+
90+
const node = svg.select("g.nodes").selectAll("circle").data(nodes);
91+
92+
// node.append("title").text(d => d.id);
11693

11794
// Add a drag behavior.
11895
node.call(
@@ -154,13 +131,32 @@ const ForceGraph: React.FC<ForceGraphProps> = ({
154131
event.subject.fx = null;
155132
event.subject.fy = null;
156133
}
157-
158-
function radius(num: number) {
159-
return num * 2;
160-
}
161134
});
162135

163-
return <svg ref={svgRef} />;
136+
function radius(num: number) {
137+
return num * 2;
138+
}
139+
140+
return (
141+
<svg
142+
ref={svgRef}
143+
width={width}
144+
height={height}
145+
viewBox={`${-width / 2} ${-height / 2} ${width}, ${height}`}
146+
style={{ height: "auto" }}
147+
>
148+
<g className="links" stroke="#999" strokeOpacity={0.6}>
149+
{links.map((link, i) => (
150+
<line key={i} strokeWidth={Math.sqrt(link.value)} />
151+
))}
152+
</g>
153+
<g className="nodes" stroke="#fff" strokeWidth={1.5}>
154+
{nodes.map((node, i) => (
155+
<circle key={i} r={radius(node.radius)} fill={color(node.group)} />
156+
))}
157+
</g>
158+
</svg>
159+
);
164160
};
165161

166162
export default ForceGraph;

0 commit comments

Comments
 (0)