使用 react+ts 和 d3 创建新的力图
Posted
技术标签:
【中文标题】使用 react+ts 和 d3 创建新的力图【英文标题】:creating new force graph with react+ts and d3 【发布时间】:2022-01-10 12:22:55 【问题描述】:我正在尝试使用 React + TS 和 D3 创建一个简单的力图。
主要问题 用线连接我的节点
这是我的代码:
import React from "react";
import forceSimulation, forceManyBody, forceLink, forceCenter from 'd3-force'
import d3 , SimulationNodeDatum from "d3";
import Box from "@mui/system";
type Node =
id: string;
class: string;
x?: string;
y?: string;
type Link =
source: string;
target: string;
connectionType: string;
数据(在同一个文件中):
const links, nodes =
nodes: [
id: "honda",
class: "cars",
,
id: "civic",
class: "cars",
,
id: "toyota",
class: "cars",
,
id: "corola",
class: "cars",
],
links: [
source: 'civic',
target: 'honda',
connectionType: 'm2o'
,
source: 'corola',
target: 'toyota',
connectionType: 'm2o'
]
...这是组件:
function Rd4Component (): JSX.Element
const simulation = forceSimulation(nodes as SimulationNodeDatum[]);
simulation
.force('charge', forceManyBody().strength(-100))
.force('link',
forceLink(links)
.id((d) => (d as Node).id)
.distance(75)
)
.force("center", forceCenter(300, 300));
const svg = d3.select('#Target');
const node = svg
.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.attr("r", 15)
.attr("stroke", "green")
.attr("stroke-width", 0.5)
.style("fill", "red");
const link = svg
.selectAll('path.link')
.data(links)
.enter()
.append("path")
.attr("stroke", "black")
.style("fill", "none");
function ticked()
link
.attr("x1", function (d: any)
return d.source.x;
)
.attr("y1", function (d: any)
return d.source.y;
)
.attr("x2", function (d: any)
return d.target.x;
)
.attr("y2", function (d: any)
return d.target.y;
);
node
.attr("cx", function (d: any)
return d.x;
)
.attr("cy", function (d: any)
return d.y;
);
// label
// .attr("x", function (d: any)
// return d.x + 5;
// )
// .attr("y", function (d: any)
// return d.y + 5;
// );
simulation.nodes(nodes as SimulationNodeDatum[])
.on("tick", ticked)
return <Box sx=overflowY: "scroll">
<svg height=600 width=600 id="Target" />
</Box>
export default Rd4Component;
结果如下:
【问题讨论】:
【参考方案1】:将path
替换为line
(或为<path>
指定d
属性而不是x1
、x2
、y1
、y1
用于<line>
)
const links, nodes =
nodes: [
id: "honda",
class: "cars",
,
id: "civic",
class: "cars",
,
id: "toyota",
class: "cars",
,
id: "corola",
class: "cars",
],
links: [
source: 'civic',
target: 'honda',
connectionType: 'm2o'
,
source: 'corola',
target: 'toyota',
connectionType: 'm2o'
]
const simulation = d3.forceSimulation(nodes);
simulation
.force('charge', d3.forceManyBody().strength(-50))
.force('link',
d3.forceLink(links)
.id((d) => d.id)
.distance(50)
)
.force("center", d3.forceCenter(100, 100));
const svg = d3.select('svg');
const link = svg
.selectAll('line.link')
.data(links)
.enter()
.append("line")
.attr("stroke", "black")
.style("fill", "none");
const node = svg
.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.attr("r", 15)
.attr("stroke", "green")
.attr("stroke-width", 0.5)
.style("fill", "red");
function ticked()
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;
);
node
.attr("cx", function (d)
return d.x;
)
.attr("cy", function (d)
return d.y;
);
// label
// .attr("x", function (d: any)
// return d.x + 5;
// )
// .attr("y", function (d: any)
// return d.y + 5;
// );
simulation.nodes(nodes)
.on("tick", ticked)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg >
</svg>
【讨论】:
以上是关于使用 react+ts 和 d3 创建新的力图的主要内容,如果未能解决你的问题,请参考以下文章