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

Javascript 将不相交的力定向图放入React应用程序,javascript,reactjs,d3.js,react-hooks,Javascript,Reactjs,D3.js,React Hooks,所以我有一个json文件,其中包含一个节点和链接数组。节点包含一个电影名称,然后映射到在其中扮演的演员。链接将电影与演员相结合。此文件存储在另一个目录中,文件路径为“./Data/nodes.json” 下面是节点的一个片段(仅一部电影,因为整个文件有32k行长) 下面是链接中的一个片段 "links": [ { "source": "Guardians of the Galaxy", "target"

所以我有一个json文件,其中包含一个节点和链接数组。节点包含一个电影名称,然后映射到在其中扮演的演员。链接将电影与演员相结合。此文件存储在另一个目录中,文件路径为“./Data/nodes.json” 下面是节点的一个片段(仅一部电影,因为整个文件有32k行长)

下面是链接中的一个片段

"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;
从“React”导入React;
导入“/App.css”;
从“d3”导入*作为d3;
从“反应请求”导入{Fetch};
类应用程序扩展了React.Component{
建造师(道具){
超级(道具);
this.myRef=React.createRef();
}
componentDidMount(){
const nodes=新请求('../Data/nodes.json');
获取(节点)。然后(response=>response.json())。然后(data=>{
//下面的循环仅显示浏览器控制台中nodes.json文件的内容
//记录这些需要很长时间
/**for(数据['nodes']的常量对象){
log(“Name:+obj['Name']);
}
用于(数据['links']的常量对象){
log(“source:+obj['source']);
log(“目标:+obj['target']);
}*/
//创建放置力定向图的位置
让svg=d3.选择(“svg”),
宽度=+svg.attr(“宽度”),
高度=+svg.attr(“高度”);
const nodes_data=数据['nodes'];
//设置模拟
//节点仅限于现在
let simulation=d3.forceSimulation()
//添加节点
.节点(节点\数据);
//加力
//我们将向每个节点添加一个电荷
//还要加一个定心力
模拟
.force(“电荷力”,d3.forceManyBody())
.力(“中心力”,d3.力中心(宽度/2,高度/2));
//为节点绘制圆
让node=svg.append(“g”)
.attr(“类”、“节点”)
.selectAll(“圆圈”)
.数据(节点\数据)
.输入()
.附加(“圆圈”)
.attr(“r”,5)
.attr(“填充”、“红色”);
//添加勾号说明:
模拟。on(“滴答声”,滴答声动作);
//链接时间到了
//创建数据链接
const links_data=数据['links'];
//创建链接力
//我们需要id访问器来使用命名的源和目标
让link\u force=d3.forceLink(links\u数据)
.id(功能(d){
返回d.name;
})
//将链接力添加到模拟中
//在d3.forceLink参数中指定链接
模拟力(“链接”,链接力)
//为链接画线
让link=svg.append(“g”)
.attr(“类”、“链接”)
.selectAll(“行”)
.数据(链接和数据)
.enter().append(“行”)
.attr(“笔划宽度”,2);
函数操作(){
//在模拟的每个记号处更新圆位置
节点
.attr(“cx”,功能(d){
返回d.x;
})
.attr(“cy”,函数(d){
返回d.y;
});
//更新链接位置
//简单地告诉行的一端跟随一个节点
//而线的另一端要跟随另一个节点左右
链接
.attr(“x1”,函数(d){
返回d.source.x;
})
.attr(“y1”,函数(d){
返回d.source.y;
})
.attr(“x2”,函数(d){
返回d.target.x;
})
.attr(“y2”,功能(d){
返回d.target.y;
});
}
});
}
render(){
返回(
);
}
}
导出默认应用程序;

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

您可以在挂载时选择“svg”,但此时它并不存在。将其添加到渲染中:

<div ref={this.myRef}>
  <svg />
</div>
<div ref={this.myRef}>
  <svg />
</div>
const svg = d3.select(this.myRef).select('svg')