Javascript d3力图中的连杆距离不正确
我有一个react应用程序,其中我试图显示一个带有指定链接距离的节点的图形。我有下面的代码,其中距离是用每个链接的值指定的。图形显示得很好,但链接距离不正确。例如,距离最远的节点的距离可能小于距离中心较近的节点的距离。有人知道为什么会这样吗?我是d3的新手,所以这一切都很混乱。Javascript d3力图中的连杆距离不正确,javascript,d3.js,force-layout,Javascript,D3.js,Force Layout,我有一个react应用程序,其中我试图显示一个带有指定链接距离的节点的图形。我有下面的代码,其中距离是用每个链接的值指定的。图形显示得很好,但链接距离不正确。例如,距离最远的节点的距离可能小于距离中心较近的节点的距离。有人知道为什么会这样吗?我是d3的新手,所以这一切都很混乱。 let FORCE=(函数(nsp){ 让它=这个, 宽度=700, 高度=500, 颜色=d3.scaleOrdinal(d3.SchemeCategory 10), PointColor=['#1769aa','洋
let FORCE=(函数(nsp){
让它=这个,
宽度=700,
高度=500,
颜色=d3.scaleOrdinal(d3.SchemeCategory 10),
PointColor=['#1769aa','洋红'],
div=d3。选择(“正文”)。追加(“div”)
.style(“不透明度”,0)
.style(“位置”、“绝对”)
.style(“文本对齐”、“居中”)
.样式(“宽度”、“220px”)
.样式(“高度”、“40px”)
.style(“填充”、“2px”)
.style(“字体系列”、“Roboto”)
.style(“背景”,“#f5”)
.style(“边框”、“0px”)
.样式(“边界半径”、“8px”)
.style(“指针事件”、“无”),
initForce=(节点、链接)=>{
nsp.force=d3.forceSimulation(节点)
.力(“电荷”,d3.力人体().力(-500))
.force(“link”,d3.forceLink(links).distance(函数(d){return(d.distance)*100;}))
.力(“中心”,d3.力中心().x(nsp.width/2).y(nsp.height/2))
.力(“碰撞”,d3.力碰撞([5])。迭代([5]);
},
enterNode=(选择)=>{
让圆=选择。选择('圆')
.attr(“r”,10)
.style(“填充”,“#1769aa”)
.style(“笔划”、“fff”)
.style(“笔划宽度”、“2px”)
.on(“鼠标悬停”,功能(d){
控制台日志(d)
让matrix=this.getScreenCTM()
.translate(+this.getAttribute(“cx”),+this.getAttribute(“cy”);
PointColor=[PointColor[1],PointColor[0]]
d3.选择(此).样式(“填充”,点颜色[0]);
过渡部()
.持续时间(200)
.style(“不透明度”,.9)
div.html(d.name+'距离:'+d.Distance)
.style(“左”(window.pageXOffset+matrix.e+15)+“px”)
.style(“top”(window.pageYOffset+matrix.f-30)+“px”)
})
.开启(“鼠标出”,功能(d){
PointColor=[PointColor[1],PointColor[0]]
d3.选择(此).样式(“填充”,点颜色[0]);
过渡部()
.持续时间(500)
.样式(“不透明度”,0);
})
.打开(“单击”,功能(d){
控制台日志(d);
打开(d.url,“u blank”);
});
选择。选择('text')
.style(“填充”、“蜜露”)
.style(“字体大小”,“600”)
.style(“文本锚定”、“中间”)
.样式(“路线基线”、“中间”)
.style(“字体大小”,“12px”)
},
updateNode=(选择)=>{
选择
.attr(“转换”,“d=>”转换(“+d.x+”,“+d.y+”))
.attr(“cx”,函数(d){return d.x=Math.max(30,Math.min(width-30,d.x));}
.attr(“cy”,函数(d){返回d.y=Math.max(30,Math.min(height-30,d.y));}
},
enterLink=(选择)=>{
选择
.attr(“笔划宽度”,2)
.attr(“笔划”,“#50505”)
},
updateLink=(选择)=>{
选择
.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.selectAll(“.node”)
.call(updateNode)
selection.selectAll(“.link”)
.呼叫(更新链接);
},
dragStarted=(d)=>{
如果(!d3.event.active)nsp.force.alphaTarget(0.3.restart();
d、 fx=d.x;
d、 fy=d.y
},
拖动=(d)=>{
d、 fx=d3.event.x;
d、 fy=d3.event.y
},
dragEnded=(d)=>{
如果(!d3.event.active)nsp.force.alphaTarget(0);
d、 fx=null;
d、 fy=null
},
拖动=()=>d3.selectAll('g.node'))
.call(d3.drag()
.on(“开始”,拖动开始)
.打开(“拖动”,拖动)
.开启(“结束”,绘图)
),
勾选=(那个)=>{
that.d3Graph=d3.select(ReactDOM.findDOMNode(that));
nsp.force.on('tick',()=>{
this.d3Graph.call(updateGraph)
});
};
nsp.width=宽度;
nsp.高度=高度;
nsp.enterNode=enterNode;
nsp.updateNode=updateNode;
nsp.enterLink=enterLink;
nsp.updateLink=updateLink;
nsp.updateGraph=updateGraph;
nsp.initForce=initForce;
nsp.dragStarted=dragStarted;
nsp.dragging=拖动;
nsp.dragEnded=dragEnded;
nsp.drag=阻力;
nsp.tick=tick;
返回nsp
})(FORCE | |{})在节点上应用了许多力,这些力处于平衡状态,可能导致链接扭曲。如果要确保指定的距离,则可以仅指定一个要开始的连接力,或随着模拟的进行逐步取消其他力(请参阅,任何一种方法都可以确保连接的长度适当(假设其几何上可能)。查看输入数据的示例会有所帮助—即“距离”原始数据集的值部分?是的,@SteveR distance是我从数据库得到的对象的一部分。看起来像这样:节点:[{“名称”:“水果”,“id”:0,“url”:“},{”名称“:“苹果”,“id”:1,“url”:“},{“名称”:“橙色”,“id”:2,“url”:“},],链接:[{“源”:0,“目标”:1,“id”:0,“距离”:.04567},
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