Javascript 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','洋

我有一个react应用程序,其中我试图显示一个带有指定链接距离的节点的图形。我有下面的代码,其中距离是用每个链接的值指定的。图形显示得很好,但链接距离不正确。例如,距离最远的节点的距离可能小于距离中心较近的节点的距离。有人知道为什么会这样吗?我是d3的新手,所以这一切都很混乱。

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