Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 设置节点之间的固定距离d3力_Javascript_D3.js_Force Layout - Fatal编程技术网

Javascript 设置节点之间的固定距离d3力

Javascript 设置节点之间的固定距离d3力,javascript,d3.js,force-layout,Javascript,D3.js,Force Layout,我试图用d3.js重现拉线灯开关的行为 您可以在代码段中看到正在运行的代码或下面的代码(最好全屏查看) 我的问题是如何将节点之间的距离设置为始终相同(就像在真正的跳线中一样) 应该拉伸的唯一链接是两个绿色节点之间的链接 我试图增加力量,但看起来不太好 //创建放置力定向图的位置 const svg=d3。选择(“svg”), 宽度=+svg.attr(“宽度”), 高度=+svg.attr(“高度”); 常量节点\u数据=[ {名称:“c1”}, {名称:“c2”}, {name:“c3”},

我试图用d3.js重现拉线灯开关的行为

您可以在代码段中看到正在运行的代码或下面的代码(最好全屏查看)

我的问题是如何将节点之间的距离设置为始终相同(就像在真正的跳线中一样)

应该拉伸的唯一链接是两个绿色节点之间的链接

我试图增加力量,但看起来不太好

//创建放置力定向图的位置
const svg=d3。选择(“svg”),
宽度=+svg.attr(“宽度”),
高度=+svg.attr(“高度”);
常量节点\u数据=[
{名称:“c1”},
{名称:“c2”},
{name:“c3”},
{名称:“c4”},
{名称:“c5”},
{name:“c6”},
];
常量链接\u数据=[
{来源:“c1”,目标:“c2”},
{来源:“c2”,目标:“c3”},
{来源:“c3”,目标:“c4”},
{来源:“c4”,目标:“c5”},
{来源:“c5”,目标:“c6”},
];
//设置模拟
const simulation=d3.forceSimulation().节点(节点\数据);
//加力
模拟力(
“很多人”,
d3.forceManyBody().distanceMin(20)distanceMax(21)
);
常量链接力=d3.forceLink(链接力数据)。距离(40)。强度(1);
链接力id(功能(d){
返回d.name;
});
模拟力(“链接”,链接力);
模拟。力(“中心”,d3。力(宽度/2)。强度(0.3));
模拟力(
“中心”,
d3
.forceY()
.y(功能(d,i){
返回高度/10+i*35;
})
.力量(功能(d,i){
返回0.4;
})
);
//为节点绘制圆
const node=svg
.附加(“g”)
.attr(“类”、“节点”)
.selectAll(“圆圈”)
.数据(节点\数据)
.输入()
.附加(“圆圈”)
.attr(“r”,10)
.attr(“填充”、“红色”)
.attr(“可拖动”、“真实”);
常量圆=d3。选择所有(“圆”)。_组[0];
常数firstCircle=d3。选择(圆[0]);
const second circle=d3.选择(圆[1]);
const lastCircle=d3.select(圆[circles.length-1]);
firstCircle.attr(“填充”、“绿色”).text(函数(d){
d、 fx=宽度/2;
d、 fy=高度/10;
控制台日志(d.fx、d.fy);
});
第二圈。属性(“填充”、“绿色”);
lastCircle.attr(“填充”、“蓝色”);
//为链接画线
const link=svg
.附加(“g”)
.attr(“类”、“链接”)
.selectAll(“行”)
.数据(链接和数据)
.输入()
.附加(“行”)
.attr(“笔划宽度”,2);
//完整的tickActions()函数
函数操作(){
//在模拟的每个记号处更新圆位置
节点
.attr(“cx”,功能(d){
返回d.x;
})
.attr(“cy”,函数(d){
返回d.y;
});
//更新链接位置
//简单地告诉行的一端跟随一个节点
//而线的另一端要跟随另一个节点左右
链接
.attr(“x1”,函数(d){
返回d.source.x;
})
.attr(“y1”,函数(d){
返回d.source.y;
})
.attr(“x2”,函数(d){
返回d.target.x;
})
.attr(“y2”,功能(d){
返回d.target.y;
});
}
模拟。on(“滴答声”,滴答声动作);
常量拖放处理程序=d3
.drag()
。打开(“开始”,拖动开始)
.打开(“拖动”,拖动)
.打开(“结束”,拖动至“结束”);
函数拖放启动(事件,d){
如果(!event.active)simulation.alphaTarget(0.3).restart();
d、 fx=d.x;
d、 fy=d.y;
}
函数拖动(事件,d){
d、 fx=事件x;
d、 fy=事件y;
}
函数拖放结束(事件,d){
如果(!event.active)simulation.alphaTarget(0);
d、 fx=null;
d、 fy=null;
d3.力()强度(0.1);
document.body.style.background==“黑色”
?(document.body.style.background=“白色”)
:(document.body.style.background=“黑色”);
console.log(document.body.style.background==“黑色”);
}
拖拽处理器(最后一圈)

D3不可能在不修改部队布局工作方式的情况下创建完美的解决方案。保持在D3的范围内,我有一个解决方案可以达到预期的结果(具有最小的弹性,这是可以接受的)

正如我在评论中指出的,d3在模拟运行时平衡了一系列的力。因此,最终的布局是力之间的折衷。我在评论中链接到的解决方案通过在模拟冷却时拨下所有其他力来获得指定链接的链接,从而允许其他力影响总体布局,而链接距离力会调整结果,以确保链接的长度正确

同样的原理也可以在这里应用,但不需要多次循环来将节点推到所需的精确位置

首先,我们像往常一样宣布我们所有的部队:

  var manybody = d3.forceManyBody().distanceMin(20).distanceMax(21);
  var x =  d3.forceX(width / 6).strength(0.3)
  var y =  d3.forceY().y(function (d, i) { return height / 10 + i * 35; })
                      .strength(0.4)
  var distance = d3.forceLink(links_data.filter(function(d,i) { return i; }))
     .distance(35)
     .id(function(d) { return d.name; })
     .strength(1);
然后我们应用它们:

  simulation
      .force("centerx",x)
      .force("centery",y)
      .force("link", distance)
      .force("many", manybody);
然后在“拖动开始”函数中,我们移除除“链接距离”函数之外的所有力。我们还将向上移动alpha并消除alpha衰减,以允许力在一个记号内将节点移动到尽可能接近其预期位置:

  function drag_start(event, d) {
    if (!event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
    // Disable other forces:
    simulation.force("centerx",null)
      .force("centery",null)
      .force("many",null);
      
    // Juice the alpha:
    simulation.alpha(1)
      .alphaDecay(0)
    
  }
在拖动结束时,我们通过重新应用力、减少alpha和增加alpha衰减来撤消在拖动开始时所做的更改:

 function drag_end(event, d) {
    // Reapply forces:
    simulation.force("centerx",x)
      .force("centery",y)
      .force("many",manybody);  
    // De-juice the alpha:
    simulation.alpha(0.2)
      .alphaDecay(0.0228)    

 ...
与规范D3相比,代码中有一些特性,但我刚刚实现了上面的更改:

//创建放置力定向图的位置
const svg=d3。选择(“svg”),
宽度=+svg.attr(“宽度”),
高度=+svg.attr(“高度”);
常量节点\u数据=[
{名称:“c1”},
{名称:“c2”},
{name:“c3”},
{名称:“c4”},
{名称:“c5”},
{name:“c6”},
];
常量链接\u数据=[
{来源:“c1”,目标:“c2”},
{来源:“c2”,目标:“c3”},
{来源:“c3”,目标:“c4”},
{来源:“c4”,目标:“c5”},
{来源:“c5”,目标:“c6”},
];
//设置模拟
常数模拟=d3.1力模拟(