增加网络/图表中节点之间的距离
Posted
技术标签:
【中文标题】增加网络/图表中节点之间的距离【英文标题】:Increase Distance Between Nodes in Network/Chart 【发布时间】:2017-12-02 10:47:36 【问题描述】:我正在尝试找出一种方法来为我的 d3.js 代码在我的网络图中分隔节点。我不必关心加载页面时网络的形状,因为我只需单击并拖动节点即可制作任何我想要的形状。但我不确定我从哪里开始尝试分隔我的节点。我四处搜寻,但没有发现任何东西似乎对我有用。非常感谢您的帮助。
这是我加载页面时网络的样子: https://i.gyazo.com/919ad4bde39d9fe6a6b6c91548dbcc2f.png
这是我希望它大致看起来的样子(同样,形状并不重要,我只是希望在初始负载上保持一点距离): https://i.gyazo.com/fefa29cf861e204bc83f34cbc2d1a17d.png
(我只有8个rep所以我不能上传图片抱歉)
到目前为止,这是我的代码:
<!DOCTYPE html>
<style>
.links line
stroke-opacity: 0.6;
.nodes circle
stroke: #fff;
stroke-width: 1.5px;
</style>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Group Comments</title>
<script src="http://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<p> Not Ready: Group 6 Comments </p>
<svg ></svg>
<script>
//fetches the svg
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
//Sets a color scale
var color = d3.scaleOrdinal(d3.schemeCategory20);
var strokeColor = d3.scaleLinear()
.domain([0, 1, 2])
.range(["white", "red", "green"]);
//Creates a force simulation
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) return d.id; ))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
//reads the JSON file
d3.json("NR6comments.json", function (error, graph)
if (error) throw error;
//sets up the "links" between the nodes
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke-width", function (d) return Math.sqrt(d.value) )
.attr("stroke", function (d) return strokeColor(d.value) );
//sets up the nodes
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", 10)
.attr("fill", function (d) return color(d.group); )
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
//displays the ID number on a node when hovering over
node.append("title")
.text(function (d) return d.id; );
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
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; );
);
function dragstarted(d)
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
function dragged(d)
d.fx = d3.event.x;
d.fy = d3.event.y;
function dragended(d)
if (!d3.event.active) simulation.alphaTarget(0);
//d.fx = null;
//d.fy = null;
</script>
<p><a href="likes.html">Likes Chart</a></p>
</body>
</html>
如果我能在这个问题上得到一些帮助,我将不胜感激。谢谢!
【问题讨论】:
【参考方案1】:有不同的方法来实现你想要的。最简单的方法是设置strength
的manyBody
方法。根据API:
如果指定了强度,则将强度访问器设置为指定的数字或函数,重新评估每个节点的强度访问器,并返回此力。正值使节点相互吸引,类似于重力,而负值使节点相互排斥,类似于静电荷。
由于我无权访问您的数据,因此这是一个简化的演示。第一个版本没有strength
,就像你的代码:
var width = 400;
var height = 300;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var nodes = [
name: "foo",
color: "blue"
,
name: "bar",
color: "green"
,
name: "baz",
color: "red"
,
name: "foofoo",
color: "yellow"
,
name: "foobar",
color: "blue"
,
name: "foobaz",
color: "green"
,
name: "barfoo",
color: "red"
,
name: "barbar",
color: "yellow"
,
name: "barbaz",
color: "blue"
];
var links = [
"source": 0,
"target": 1
,
"source": 0,
"target": 2
,
"source": 0,
"target": 3
,
"source": 1,
"target": 3
,
"source": 1,
"target": 4
,
"source": 2,
"target": 5
,
"source": 3,
"target": 6
,
"source": 1,
"target": 7
,
"source": 6,
"target": 8
,
"source": 0,
"target": 7
,
"source": 2,
"target": 6
,
"source": 3,
"target": 8
];
var simulation = d3.forceSimulation()
.force("link", d3.forceLink())
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
var link = svg.selectAll(null)
.data(links)
.enter()
.append("line")
.style("stroke", "#ccc")
.style("stroke-width", 1);
var node = svg.selectAll(null)
.data(nodes)
.enter()
.append("circle")
.attr("r", function(d)
return d.r = 10;
)
.attr("stroke", "gray")
.attr("stroke-width", "2px")
.attr("fill", function(d)
return d.color
);
simulation.nodes(nodes);
simulation.force("link")
.links(links);
simulation.on("tick", function()
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
);
);
<script src="https://d3js.org/d3.v4.min.js"></script>
然而,第二个版本将strength
设置为负值:
.force("charge", d3.forceManyBody().strength(-500))
这里是:
var width = 400;
var height = 300;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var nodes = [
name: "foo",
color: "blue"
,
name: "bar",
color: "green"
,
name: "baz",
color: "red"
,
name: "foofoo",
color: "yellow"
,
name: "foobar",
color: "blue"
,
name: "foobaz",
color: "green"
,
name: "barfoo",
color: "red"
,
name: "barbar",
color: "yellow"
,
name: "barbaz",
color: "blue"
];
var links = [
"source": 0,
"target": 1
,
"source": 0,
"target": 2
,
"source": 0,
"target": 3
,
"source": 1,
"target": 3
,
"source": 1,
"target": 4
,
"source": 2,
"target": 5
,
"source": 3,
"target": 6
,
"source": 1,
"target": 7
,
"source": 6,
"target": 8
,
"source": 0,
"target": 7
,
"source": 2,
"target": 6
,
"source": 3,
"target": 8
];
var simulation = d3.forceSimulation()
.force("link", d3.forceLink())
.force("charge", d3.forceManyBody().strength(-500))
.force("center", d3.forceCenter(width / 2, height / 2));
var link = svg.selectAll(null)
.data(links)
.enter()
.append("line")
.style("stroke", "#ccc")
.style("stroke-width", 1);
var node = svg.selectAll(null)
.data(nodes)
.enter()
.append("circle")
.attr("r", function(d)
return d.r = 10;
)
.attr("stroke", "gray")
.attr("stroke-width", "2px")
.attr("fill", function(d)
return d.color
);
simulation.nodes(nodes);
simulation.force("link")
.links(links);
simulation.on("tick", function()
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
);
);
<script src="https://d3js.org/d3.v4.min.js"></script>
【讨论】:
好心的先生,值得一吃!太感谢了!我假设如果我想要更多的距离,我只会让这个数字越来越负?有没有办法让我可以将值设置为可能的最小值,而无需任何节点离开画布? .strength(-500) 对我的大部分数据都非常好,但如果节点太多,那么我可能需要将其更改为 like .strength(-200) 之类的。那么有没有一种方法可以自动为我确定最佳强度值?非常感谢! 正如我所说,这只是一种方法......例如,您也可以使用链接距离。以上是关于增加网络/图表中节点之间的距离的主要内容,如果未能解决你的问题,请参考以下文章