将不相交的力有向图放入 React 应用程序

Posted

技术标签:

【中文标题】将不相交的力有向图放入 React 应用程序【英文标题】:Put a disjoint force directed graph into React app 【发布时间】:2021-07-06 10:50:07 【问题描述】:

所以我有一个包含节点和链接数组的 json 文件。节点包含一个电影名称,然后映射到其中播放的演员。链接将电影与演员结合起来。该文件存储在另一个目录中,文件路径为“../Data/nodes.json” 这是来自节点的 sn-p(只有一部电影,因为整个文件有 32k 行长)

"nodes": [
  
   "name": "Guardians of the Galaxy",
   "id": "1"
  ,
  
   "name": "Chris Pratt"
  ,
  
   "name": "Vin Diesel"
  ,
  
   "name": "Bradley Cooper"
  ,
  
   "name": "Zoe Saldana"
  
]

这是来自链接的sn-p

"links": [
  
   "source": "Guardians of the Galaxy",
   "target": "Chris Pratt"
  ,
  
   "source": "Guardians of the Galaxy",
   "target": "Vin Diesel"
  ,
  
   "source": "Guardians of the Galaxy",
   "target": "Bradley Cooper"
  ,
  
   "source": "Guardians of the Galaxy",
   "target": "Zoe Saldana"
  
]

我的目标是在使用 D3 制作后,尝试在 React GUI 上显示这个不相交的力有向图。我找不到任何可以提供帮助的教程。 这是我目前的 App.js...

import React from 'react';
import './App.css';
import * as d3 from 'd3';
import  Fetch  from 'react-request';

class App extends React.Component
    constructor(props) 
        super(props);
        this.myRef = React.createRef();
    

    componentDidMount() 
        const nodes = new Request('../Data/nodes.json');
        fetch(nodes).then(response => response.json()).then(data => 
            //loops below just display contents of our nodes.json file in the browser's console
            //it takes FOREVER to log these
           /** for (const obj of data['nodes'])
            console.log("Name: " + obj['name']);
        

             for (const obj of data['links'])
            console.log("source: " + obj['source']);
            console.log("target: " + obj['target']);
        */

                //create somewhere to put the force directed graph
            let svg = d3.select("svg"),
                width = +svg.attr("width"),
                height = +svg.attr("height");


            const nodes_data = data['nodes'];


            //set up the simulation
            //nodes only for now
            let simulation = d3.forceSimulation()
                //add nodes
                .nodes(nodes_data);

            //add forces
            //we're going to add a charge to each node
            //also going to add a centering force
            simulation
                .force("charge_force", d3.forceManyBody())
                .force("center_force", d3.forceCenter(width / 2, height / 2));


            //draw circles for the nodes
            let node = svg.append("g")
                .attr("class", "nodes")
                .selectAll("circle")
                .data(nodes_data)
                .enter()
                .append("circle")
                .attr("r", 5)
                .attr("fill", "red");


            //add tick instructions:
            simulation.on("tick", tickActions);


            //Time for the links

            //Create links data
            const links_data = data['links'];


            //Create the link force
            //We need the id accessor to use named sources and targets

            let link_force = d3.forceLink(links_data)
                .id(function (d) 
                    return d.name;
                )

            //Add a links force to the simulation
            //Specify links  in d3.forceLink argument


            simulation.force("links", link_force)

            //draw lines for the links
            let link = svg.append("g")
                .attr("class", "links")
                .selectAll("line")
                .data(links_data)
                .enter().append("line")
                .attr("stroke-width", 2);


            function tickActions() 
                //update circle positions each tick of the simulation
                node
                    .attr("cx", function (d) 
                        return d.x;
                    )
                    .attr("cy", function (d) 
                        return d.y;
                    );

                //update link positions
                //simply tells one end of the line to follow one node around
                //and the other end of the line to follow the other node around
                link
                    .attr("x1", function (d) 
                        return d.source.x;
                    )
                    .attr("y1", function (d) 
                        return d.source.y;
                    )
                    .attr("x2", function (d) 
                        return d.target.x;
                    )
                    .attr("y2", function (d) 
                        return d.target.y;
                    );

            
        );

    

    render()
        return (
            <div ref=this.myRef>
            </div>
        );
    

export default App;

如果可能的话,我还希望将来能够将我制作的 NavBar.js 类添加到 GUI 的顶部。

【问题讨论】:

【参考方案1】:

您在安装时选择了“svg”,但此时它不存在。将其添加到渲染中:

<div ref=this.myRef>
  <svg />
</div>

...然后在 mount 时正确选择 svg:

const svg = d3.select(this.myRef).select('svg')

【讨论】:

以上是关于将不相交的力有向图放入 React 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

有向图中的 K 条边不相交路径

Treasure Exploration POJ - 2594 有向图路径可相交的最小路径覆盖模板题

React Native:如何从循环中获取值到钩子 useState

防止力有向图中的节点重叠

图中具有特定长度的顶点不相交路径

Air Raid POJ - 1422 有向无环图(DAG)的最小路径覆盖最小不相交路径覆盖 模板题