我有一个React应用程序,试图显示具有指定链接距离的节点的图。我下面有以下代码,其中为每个链接指定了距离。该图显示良好,但链接距离不正确。例如,最远的节点的距离可以小于更靠近中心的节点的距离。有谁知道为什么会这样?我是d3的新手,所以这一切都很令人困惑。
let FORCE = (function(nsp){
let that = this,
width = 700,
height = 500,
color = d3.scaleOrdinal(d3.schemeCategory10),
PointColors = ['#1769aa', 'magenta'],
div = d3.select("body").append("div")
.style("opacity", 0)
.style("position", "absolute")
.style("text-align", "center")
.style("width", "220px")
.style("height", "40px")
.style("padding", "2px")
.style("font-family", "Roboto")
.style("background", "#f5f5f5")
.style("border", "0px")
.style("border-radius", "8px")
.style("pointer-events", "none"),
initForce = (nodes, links) => {
nsp.force = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-500))
.force("link", d3.forceLink(links).distance(function (d) { return (d.distance)*100;}))
.force("center", d3.forceCenter().x(nsp.width /2).y(nsp.height / 2))
.force("collide", d3.forceCollide([5]).iterations([5]));
},
enterNode = (selection) => {
let circle = selection.select('circle')
.attr("r", 10)
.style("fill", '#1769aa' )
.style("stroke", "#fff")
.style("stroke-width", "2px")
.on("mouseover", function(d){
console.log(d)
let matrix = this.getScreenCTM()
.translate(+ this.getAttribute("cx"), + this.getAttribute("cy"));
PointColors = [PointColors[1], PointColors[0]]
d3.select(this).style("fill", PointColors[0]);
div.transition()
.duration(200)
.style("opacity", .9)
div.html(d.name+'</br>Distance: '+d.distance)
.style("left", (window.pageXOffset + matrix.e + 15) + "px")
.style("top", (window.pageYOffset + matrix.f - 30) + "px")
})
.on("mouseout", function(d) {
PointColors = [PointColors[1], PointColors[0]]
d3.select(this).style("fill", PointColors[0]);
div.transition()
.duration(500)
.style("opacity", 0);
})
.on("click", function(d) {
console.log(d);
window.open(d.url, '_blank');
});
selection.select('text')
.style("fill", "honeydew")
.style("font-weight", "600")
.style("text-anchor", "middle")
.style("alignment-baseline", "middle")
.style("font-size", "12px")
},
updateNode = (selection) => {
selection
.attr("transform", (d) => "translate(" + d.x + "," + d.y + ")")
.attr("cx", function(d) { return d.x = Math.max(30, Math.min(width - 30, d.x)); })
.attr("cy", function(d) { return d.y = Math.max(30, Math.min(height - 30, d.y)); })
},
enterLink = (selection) => {
selection
.attr("stroke-width", 2)
.attr("stroke","#505050")
},
updateLink = (selection) => {
selection
.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);
},
updateGraph = (selection) => {
selection.selectAll('.node')
.call(updateNode)
selection.selectAll('.link')
.call(updateLink);
},
dragStarted = (d) => {
if (!d3.event.active) nsp.force.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y
},
dragging = (d) => {
d.fx = d3.event.x;
d.fy = d3.event.y
},
dragEnded = (d) => {
if (!d3.event.active) nsp.force.alphaTarget(0);
d.fx = null;
d.fy = null
},
drag = () => d3.selectAll('g.node')
.call(d3.drag()
.on("start", dragStarted)
.on("drag", dragging)
.on("end", dragEnded)
),
tick = (that) => {
that.d3Graph = d3.select(ReactDOM.findDOMNode(that));
nsp.force.on('tick', () => {
that.d3Graph.call(updateGraph)
});
};
nsp.width = width;
nsp.height = height;
nsp.enterNode = enterNode;
nsp.updateNode = updateNode;
nsp.enterLink = enterLink;
nsp.updateLink = updateLink;
nsp.updateGraph = updateGraph;
nsp.initForce = initForce;
nsp.dragStarted = dragStarted;
nsp.dragging = dragging;
nsp.dragEnded = dragEnded;
nsp.drag = drag;
nsp.tick = tick;
return nsp
})(FORCE || {})