[英]How to render a large graph smoothly as a react.js component?
我想可视化大图,但 UI 冻结并且 V8 引擎在大约 25 秒后抛出内存不足错误。
理想情况下,我希望图形渲染流畅且无阻塞。
我的Graph.js
文件在按下“设置”按钮时将图形点字符串分配给src
变量,并在按下“渲染”按钮时尝试显示图形。
import React, { useRef, useState } from 'react';
import Viz from 'viz.js';
import { Module, render } from 'viz.js/full.render.js';
const largegraph = "digraph { " + Array.from(Array(1000).keys()).map(i => "a" + i + " [label=" + i + "];").join(" ") + Array.from(Array(10000).keys()).map(i => "a" + Math.floor(Math.random() * 1000) + " -> " + "a" + Math.floor(Math.random() * 1000) + ";").join(" ") + " }";
function GraphvizGraph(props) {
const container = useRef(null);
const [src, setSrc] = useState(props.src);
const renderGraph = (src) => {
const viz = new Viz({ Module, render });
viz.renderSVGElement(src)
.then(function (element) {
container.current.innerHTML = "";
container.current.appendChild(element);
});
}
console.log(largegraph)
return (
<div>
<button onClick={() => setSrc(largegraph)}>Set</button>
<button onClick={() => renderGraph(src)}>Render</button>
<div ref={container} />
</div>
);
}
export default GraphvizGraph;
设置大图后,点击“Render”按钮无法显示任何内容并导致UI卡顿。 几秒钟后,Chrome 抛出异常。 有没有办法解决这个问题并成功地平滑地可视化图形?
full.render.js:24 Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value 16777216, (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0
abort @ full.render.js:24
react-dom.development.js:4161 [Violation] 'click' handler took 23773ms
[Violation] 'click' handler took 23773ms
Uncaught (in promise) abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value 16777216, (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 "). Build with -s ASSERTIONS=1 for more info.
go 关于提高图形渲染性能有几种方法。 第一个是调整图形属性,如nslimit
、 maxiter
和splines
。 将它们调整得不那么复杂可以提供显着的加速以换取“吸引力”。
另一种方法是使用不同的布局引擎。 viz.renderSVGElement()
默认使用dot
布局引擎,速度不是特别快。 osage
和twopi
通常要快得多,但他们也会用它来换取“吸引力”。 为了指定要使用的布局引擎,viz.renderSVGElement(src, renderOptions)
采用第二个参数,即渲染选项object,您可以在其中设置{engine: "osage"}
。
其他注意事项:
overlap=false;
到您的图形属性,以确保节点不重叠并保持一定的可读性。dangerouslySetInnerHTML
来渲染它。function GraphvizGraph(props) {
const [src, setSrc] = useState(props.src);
const [svgStr, setSvgStr] = useState("");
const renderGraph = (src) => {
const viz = new Viz({ Module, render });
viz.renderSVGElement(src, {engine: "osage"})
.then((svg) => setSvgStr(svg.outerHTML));
}
console.log(largegraph)
return (
<div>
<button onClick={() => setSrc(largegraph)}>Set</button>
<button onClick={() => renderGraph(src)}>Render</button>
<div dangerouslySetInnerHTML={{__html: svgStr}} />
</div>
);
}
我做了一些类似于之前建议的事情,只是使用hpcc-js/wasm/graphviz ,这似乎是 OP 提到的viz.js
更成熟的解决方案。
import './App.css';
import { Graphviz } from "@hpcc-js/wasm/graphviz";
import React from 'react';
function Graph(props) {
const [svg, setSvg] = React.useState(null);
React.useEffect(() => {
async function name(params) {
const graphviz = await Graphviz.load();
const dot = `digraph G5 {
edge [fontcolor=black fontsize="10" fontname=Arial];
subgraph referenceNodes {
node [style="filled" fontcolor=white fontsize="12" fontname=Arial];
subgraph person {
node [fillcolor="blue"];
person_JaneDoe [label="<person>\nJane Doe"];
person_WendyDoe [label="<person>\nWendy Doe"];
person_StacyDoe [label="<person>\nStacy Doe"];
}
subgraph profession {
node [fillcolor="darkGreen"];
profession_Programmer [label="<profession>\nProgrammer"];
profession_Writer [label="<profession>\nWriter"];
}
subgraph vehicle {
node [fillcolor="purple"];
vehicle_Subaru [label="<vehicle>\nSubaru"];
vehicle_Ford [label="<vehicle>\nFord"];
}
}
subgraph dataNodes {
node [shape=box style="filled" fillcolor=yellow fontcolor=black fontsize="12" fontname=Arial];
value_age24_1 [label="<integer>\n24";];
value_age24_2 [label="<integer>\n24";];
value_age21_1 [label="<integer>\n21";];
}
subgraph JaneDoe {
person_JaneDoe -> person_WendyDoe [label=" has sister" dir=both];
person_JaneDoe -> person_StacyDoe [label=" has sister" dir=both];
person_JaneDoe -> profession_Programmer [label=" is a"];
person_JaneDoe -> vehicle_Subaru [label=" owns a"];
person_JaneDoe -> value_age24_1 [label="has age"];
}
subgraph WendyDoe {
person_WendyDoe -> profession_Writer [label=" is a"];
person_WendyDoe -> vehicle_Subaru [label=" owns a"];
person_WendyDoe -> value_age24_2 [label="has age"];
person_WendyDoe -> person_StacyDoe [label=" has sister" dir=both];
}
subgraph StacyDoe {
person_StacyDoe -> profession_Writer [label="is a"]
person_StacyDoe -> vehicle_Ford [label="owns a"]
person_StacyDoe -> value_age21_1 [label="has age"];
}
}`;
const svg_tmp = graphviz.dot(dot);
setSvg(svg_tmp);
console.log(graphviz.version(), svg_tmp);
} name();
}, [])
return <div>
<div dangerouslySetInnerHTML={{ __html: svg }} />
</div>
}
function App() {
return (
<div className="App">
<Graph />
</div>
);
}
export default App;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.