d3.js - 强制布局边界问题V4 [英] d3.js - Force-Layout boundary issue V4
问题描述
目前我正在开展FCC的项目之一 National Contiguity
Currently I am working one of FCC's project National Contiguity
基本上我能够弄清楚如何渲染标志精灵并连接节点及其链接。
Essentially I was able to figure it out how to render the flags sprites and connect the nodes and its links.
我唯一遇到的问题是如何实现类似FCC的示例的。具体来说,我正在尝试让节点像示例中那样排斥边界。
The only thing that I am having trouble is implementing is how to behave similar to FCC's example. Specifically I am trying ways to have the nodes to repel away from the boundries like in the example.
然而,我的行为并不那样(事实上,它非常已集群,但我不确切知道 d3.js强制文档中的哪些属性V4 我应该研究一下)。相反,似乎虽然节点和链接在边界附近停止,但它在那时停止
However, mine doesn't behave that way (in fact, it's very clustered but I don't know exactly what properties in the d3.js Force Documents V4 I should look into). Instead, it seems that though the node and the links stops near the boundary, it stops at that point
const width = w - (margin.left + margin.right);
const height = h - (margin.top + margin.bottom);
let flagNodes = d3.select("#canvas")
.append("div")
.classed("flag-nodes",true)
let svg = d3.select("#canvas")
.append("svg")
.attr("id","chart")
.attr("width", w)
.attr("height", h)
let chart = svg.append("g")
.classed("display", true)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
let simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d,i) {
return i;
}))
.force("charge", d3.forceManyBody().strength(-60).distanceMax(50).distanceMin(5))
.force("center", d3.forceCenter(width/2, height/2))
.force("collide", d3.forceCollide().radius(35))
// .force("centering", d3.forceCenter(,height))
// .force("position", d3.forceX(0).strength(.01))
// .force("position", d3.forceY(-18))
let link = chart.append("g")
.classed("links",true)
.selectAll("line")
.data(data.links)
.enter()
.append("line")
simulation
.nodes(data.nodes)
.on("tick", ticked);
simulation
.force("link")
.links(data.links);
let node = flagNodes.selectAll(".flag-nodes")
.data(data.nodes)
.enter()
.append("div")
.attr("class", function(d,i){
return `flag flag-${d.code}`
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended)
)
node.append("title")
.text(function(d) { return d.country; });
d3.forceX(width)
//functions provided by D3.js
//
function ticked() {
node
.style("left", function(d) {
let xlimit = Math.max(radius, Math.min(width - radius, d.x))
return (xlimit) + 'px'
})
.style("top", function(d) {
let ylimit = Math.max(radius, Math.min(height - radius, d.y))
return (ylimit - 2) + 'px'
});
link
.attr("x1", function(d) {
let x1 = Math.max(radius, Math.min(width - radius, d.source.x))
return x1;
})
.attr("y1", function(d) {
let y1 = Math.max(radius, Math.min(height - radius, d.source.y))
return y1
})
.attr("x2", function(d) {
let x2 = Math.max(radius, Math.min(width - radius, d.target.x))
return x2;
})
.attr("y2", function(d) {
let y2 = Math.max(radius, Math.min(height - radius, d.target.y))
return y2
});
}
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;
}
推荐答案
在每个刻度线上运行此函数在模拟的节点上:
On every tick, run this function on the simulation's nodes:
fixBounds() {
const graphNodes = this.forceSimulation.nodes();
graphNodes.forEach((node) => {
if (node.x - this.nodeRadius < 0) {
node.x = this.nodeRadius;
node.vx = 0;
}
if (node.y - this.nodeRadius < 0) {
node.y = this.nodeRadius;
node.vy = 0;
}
if (this.width && node.x + this.nodeRadius > this.width) {
node.x = this.width - this.nodeRadius;
node.vx = 0;
}
if (this.height && node.y + this.nodeRadius > this.height) {
node.y = this.height - this.nodeRadius;
node.yx = 0;
}
})
}
这会导致节点卡在边框上,节点之间的力会导致它们移动远离边境。
This will cause the nodes to get stuck on the border, and the forces between the nodes will cause them to move away from the border.
这篇关于d3.js - 强制布局边界问题V4的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!