繁体   English   中英

如何将大图平滑渲染为 react.js 组件?

[英]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 关于提高图形渲染性能有几种方法。 第一个是调整图形属性,如nslimitmaxitersplines 将它们调整得不那么复杂可以提供显着的加速以换取“吸引力”。

另一种方法是使用不同的布局引擎。 viz.renderSVGElement()默认使用dot布局引擎,速度不是特别快。 osagetwopi通常要快得多,但他们也会用它来换取“吸引力”。 为了指定要使用的布局引擎,viz.renderSVGElement(src, renderOptions)采用第二个参数,即渲染选项object,您可以在其中设置{engine: "osage"}

其他注意事项

  • 您可能应该添加overlap=false; 到您的图形属性,以确保节点不重叠并保持一定的可读性。
  • 对于最惯用的 React 代码并防止潜在的错误重新渲染,将 SVG 字符串保存到组件 state,并使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM