当它们 link(使用 d3.js)时节点的位置发生变化
Position of node changes when they link (using d3.js)
我是 d3.js 的新手。我尝试创建一个包含 5 个节点的静态架构,并且 link 它们根据偏好相互组合,节点应该像这样组织:
一开始我设置了节点的位置,然后创建了 links。但是,当节点得到 linked 时,体系结构发生变化,结果如下所示:
这是我的代码:
var width = 640,
height = 400;
var nodes = [
{ x: 60, y: 0, id: 0},
{ x: 150, y: height/4, id: 1},
{ x: 220, y: height/4, id: 2},
{ x: 340, y: height/4, id: 3},
{ x: 420, y: height/2, id: 4},
{ x: 480, y: height/2, id: 5}
];
var links = [
{ source: 1, target: 5 },
{ source: 0, target: 5 },
{ source: 2, target: 1 },
{ source: 3, target: 2 },
{ source: 4, target: 5 }
];
var graph = d3.select('#graph');
var svg = graph.append('svg')
.attr('width', width)
.attr('height', height);
var force = d3.layout.force()
.size([width, height])
.nodes(nodes)
.links(links);
force.linkDistance(width/2);
var link = svg.selectAll('.link')
.data(links)
.enter().append('line')
.attr('class', 'link');
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
var node = svg.selectAll('.node')
.data(nodes)
.enter().append("circle")
.attr("cx", d=> d.x)
.attr("cy", d=> d.y)
.attr('class', 'node')
.on("mouseover", function(d){
d3.select(this)
.transition()
.duration(500)
.style("cursor", "pointer")
div
.transition()
.duration(300)
.style("opacity", "1")
.style("display", "block")
console.log("label", d.label);
div
.html("IP: " + d.label + " x: " + d.x + " y: " + d.y)
.style("left", (d3.event.pageX ) + "px")
.style("top", (d3.event.pageY) + "px");
})
.on("mouseout", mouseout);
function mouseout() {
div.transition()
.duration(300)
.style("opacity", "0")
}
console.log("wait...");
force.on('end', function() {
node.attr('r', width/25)
.attr('cx', function(d) { return d.x; })
.attr('cy', function(d) { return d.y; });
link.attr('x1', function(d) { console.log("LINE x1-> ", d.source.x); return d.source.x; })
.attr('y1', function(d) { console.log("LINE y1-> ", d.source.y); return d.source.y; })
.attr('x2', function(d) { console.log("LINE x2-> ", d.source.x); return d.target.x; })
.attr('y2', function(d) { console.log("LINE y2-> ", d.source.y); return d.target.y; })
.attr("stroke-width", 2)
.attr("stroke","black");
});
force.start();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="graph"></div>
你能帮帮我吗?
先感谢您。
强制布局具有一些优势,这些优势源自其作为自组织布局的性质:
- 它自动放置节点和链接,避免手动定位可能有数千个元素
- 它根据分配的力将节点和链接组织到理想的间距和布局
您的节点已经 分配了位置,上面列出的两个优点不适用。您已经手动完成了第一项,第二项会打乱并覆盖您手动设置的位置。
我们可以fix the node positions,但是如果我们对所有节点都这样做,它就违背了力布局的目的:通过模拟力来定位节点。
相反,如果你有所有节点的位置,我们可以跳过强制,只根据数据附加所有内容。下面的代码片段使用 d.source
/d.target
中包含的索引首先放置链接(因此它们在节点后面)以访问 nodes
数组中的特定节点并获取适当的 x 或坐标。节点正常定位。
虽然屏幕截图使用图像(正如您在上一个问题中也使用的那样),但您似乎已经调整了代码以在您的问题中使用圆圈,我将在这里使用圆圈。根据您给出的坐标,一些线重叠。我修改了第一个节点,使 y 值不为 0(这会将半个圆推离 svg)
var width = 640,
height = 400;
var nodes = [
{ x: 60, y: height/8, id: 0},
{ x: 150, y: height/4, id: 1},
{ x: 220, y: height/4, id: 2},
{ x: 340, y: height/4, id: 3},
{ x: 420, y: height/2, id: 4},
{ x: 480, y: height/2, id: 5}
];
var links = [
{ source: 1, target: 5 },
{ source: 0, target: 5 },
{ source: 2, target: 1 },
{ source: 3, target: 2 },
{ source: 4, target: 5 }
];
var graph = d3.select('#graph');
var svg = graph.append('svg')
.attr('width', width)
.attr('height', height);
// append links:
svg.selectAll()
.data(links)
.enter()
.append("line")
.attr("x1", function(d) { return nodes[d.source].x; })
.attr("y1", function(d) { return nodes[d.source].y; })
.attr("x2", function(d) { return nodes[d.target].x; })
.attr("y2", function(d) { return nodes[d.target].y; })
.attr("stroke-width", 2)
.attr("stroke","black");
// append nodes:
svg.selectAll()
.data(nodes)
.enter()
.append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", 8);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="graph"></div>
我是 d3.js 的新手。我尝试创建一个包含 5 个节点的静态架构,并且 link 它们根据偏好相互组合,节点应该像这样组织:
一开始我设置了节点的位置,然后创建了 links。但是,当节点得到 linked 时,体系结构发生变化,结果如下所示:
这是我的代码:
var width = 640,
height = 400;
var nodes = [
{ x: 60, y: 0, id: 0},
{ x: 150, y: height/4, id: 1},
{ x: 220, y: height/4, id: 2},
{ x: 340, y: height/4, id: 3},
{ x: 420, y: height/2, id: 4},
{ x: 480, y: height/2, id: 5}
];
var links = [
{ source: 1, target: 5 },
{ source: 0, target: 5 },
{ source: 2, target: 1 },
{ source: 3, target: 2 },
{ source: 4, target: 5 }
];
var graph = d3.select('#graph');
var svg = graph.append('svg')
.attr('width', width)
.attr('height', height);
var force = d3.layout.force()
.size([width, height])
.nodes(nodes)
.links(links);
force.linkDistance(width/2);
var link = svg.selectAll('.link')
.data(links)
.enter().append('line')
.attr('class', 'link');
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
var node = svg.selectAll('.node')
.data(nodes)
.enter().append("circle")
.attr("cx", d=> d.x)
.attr("cy", d=> d.y)
.attr('class', 'node')
.on("mouseover", function(d){
d3.select(this)
.transition()
.duration(500)
.style("cursor", "pointer")
div
.transition()
.duration(300)
.style("opacity", "1")
.style("display", "block")
console.log("label", d.label);
div
.html("IP: " + d.label + " x: " + d.x + " y: " + d.y)
.style("left", (d3.event.pageX ) + "px")
.style("top", (d3.event.pageY) + "px");
})
.on("mouseout", mouseout);
function mouseout() {
div.transition()
.duration(300)
.style("opacity", "0")
}
console.log("wait...");
force.on('end', function() {
node.attr('r', width/25)
.attr('cx', function(d) { return d.x; })
.attr('cy', function(d) { return d.y; });
link.attr('x1', function(d) { console.log("LINE x1-> ", d.source.x); return d.source.x; })
.attr('y1', function(d) { console.log("LINE y1-> ", d.source.y); return d.source.y; })
.attr('x2', function(d) { console.log("LINE x2-> ", d.source.x); return d.target.x; })
.attr('y2', function(d) { console.log("LINE y2-> ", d.source.y); return d.target.y; })
.attr("stroke-width", 2)
.attr("stroke","black");
});
force.start();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="graph"></div>
你能帮帮我吗? 先感谢您。
强制布局具有一些优势,这些优势源自其作为自组织布局的性质:
- 它自动放置节点和链接,避免手动定位可能有数千个元素
- 它根据分配的力将节点和链接组织到理想的间距和布局
您的节点已经 分配了位置,上面列出的两个优点不适用。您已经手动完成了第一项,第二项会打乱并覆盖您手动设置的位置。
我们可以fix the node positions,但是如果我们对所有节点都这样做,它就违背了力布局的目的:通过模拟力来定位节点。
相反,如果你有所有节点的位置,我们可以跳过强制,只根据数据附加所有内容。下面的代码片段使用 d.source
/d.target
中包含的索引首先放置链接(因此它们在节点后面)以访问 nodes
数组中的特定节点并获取适当的 x 或坐标。节点正常定位。
虽然屏幕截图使用图像(正如您在上一个问题中也使用的那样),但您似乎已经调整了代码以在您的问题中使用圆圈,我将在这里使用圆圈。根据您给出的坐标,一些线重叠。我修改了第一个节点,使 y 值不为 0(这会将半个圆推离 svg)
var width = 640,
height = 400;
var nodes = [
{ x: 60, y: height/8, id: 0},
{ x: 150, y: height/4, id: 1},
{ x: 220, y: height/4, id: 2},
{ x: 340, y: height/4, id: 3},
{ x: 420, y: height/2, id: 4},
{ x: 480, y: height/2, id: 5}
];
var links = [
{ source: 1, target: 5 },
{ source: 0, target: 5 },
{ source: 2, target: 1 },
{ source: 3, target: 2 },
{ source: 4, target: 5 }
];
var graph = d3.select('#graph');
var svg = graph.append('svg')
.attr('width', width)
.attr('height', height);
// append links:
svg.selectAll()
.data(links)
.enter()
.append("line")
.attr("x1", function(d) { return nodes[d.source].x; })
.attr("y1", function(d) { return nodes[d.source].y; })
.attr("x2", function(d) { return nodes[d.target].x; })
.attr("y2", function(d) { return nodes[d.target].y; })
.attr("stroke-width", 2)
.attr("stroke","black");
// append nodes:
svg.selectAll()
.data(nodes)
.enter()
.append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", 8);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="graph"></div>