Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/442.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_Svg_D3.js_Tree_Force Layout - Fatal编程技术网

Javascript d3力有向图向下力模拟

Javascript d3力有向图向下力模拟,javascript,svg,d3.js,tree,force-layout,Javascript,Svg,D3.js,Tree,Force Layout,也许这不是最好的方法,但现在我已经进入了兔子洞,我想知道它是如何工作的。我试着用d3创建一棵树,在那里节点会向下沉降,就像重力一样。我希望这个,再加上每个节点的电荷和绳子的张力,能让它看起来像我想象的那样,平衡自己。我试图在d3中模拟这种恒定的向下加速度,但我是d3的初学者,不知道确切的方法。我还遇到了一个问题,模拟停止运行,d3.timer(force.resume)没有帮助 因此,本质上,我希望将根节点固定在某个特定位置,如枢轴,子节点脱离它,重力、电荷和张力都存在,这样子节点就可以自动稳定

也许这不是最好的方法,但现在我已经进入了兔子洞,我想知道它是如何工作的。我试着用d3创建一棵树,在那里节点会向下沉降,就像重力一样。我希望这个,再加上每个节点的电荷和绳子的张力,能让它看起来像我想象的那样,平衡自己。我试图在d3中模拟这种恒定的向下加速度,但我是d3的初学者,不知道确切的方法。我还遇到了一个问题,模拟停止运行,d3.timer(force.resume)没有帮助


因此,本质上,我希望将根节点固定在某个特定位置,如枢轴,子节点脱离它,重力、电荷和张力都存在,这样子节点就可以自动稳定下来,并将自己平衡到树结构中。

力导向模拟是布置树、图表或图形的好方法。许多开源和商业图书馆和应用程序都使用这种方法,因此D3只是其中之一。而且,这个话题一直吸引着应用数学家的注意

我只想告诉你这是一个巨大的话题。如果你把自己局限于D3,那么还有很多方法可以实现你在问题中所描述的。由于这个答案必须有一个合理的长度,我将通过3个D3示例向您展示一些亮点。我将从一个简单的强制导向树布局示例开始(这并不是您真正想要的,但很简单),每个示例都将建立在前面的基础上,并且更接近您想要实现的目标

例1

这是通过D3力布局以径向方式布置的树的基本示例。您确实需要理解所有使用的代码。我只想在这里提到一些亮点:

  • 函数getData()返回一个测试树(这是一个方便的子集 所谓的“flare”测试树)
  • 函数
    flant()
    将树对象转换为数组,这是初始化D3 force布局所需的格式
  • 初始化所有节点的位置(否则D3 force布局会表现得有点奇怪和不可预测)
  • 根节点位置初始化为图的中心,根节点声明为固定
  • 提供了“ontick”功能,它只是按照模拟过程中的行为绘制链接和节点
  • D3力布局算法初始化为D3重力0.2和D3电荷-200
  • D3 force布局算法通过调用其方法start()启动
如果您有与此示例相关的其他问题,请告诉我。我知道,对于没有D3经验的人来说,代码看起来有点奇怪——但实际上,一旦你了解了D3Force布局,代码就非常简单,也很容易理解。您可以使用不同的D3重力和D3电荷,以更好地理解为什么选择特定值0.2和-200

当然,这不是你想要的,但它可以作为我们的“典范”

例2

就代码而言,本例与previus的不同之处在于两个方面:

  • 根节点位置初始化为(宽度/2100)而不是(宽度/2,高度/2)-这是“悬挂”布局根的自然位置
  • 自定义力在“ontick”函数中定义为以下几行:
var ky=e.alpha;

links.forEach(函数(d,i){

d.target.y+=(d.target.depth*100-d.target.y)*5*ky;

});

这个自定义力将把相同深度的节点吸引到同一条水平线上。这足以在图片中生成图表

但是,您可以注意到图中某些节点的非自然排列-通常,它们看起来并不完全像是从父节点“挂起”的。下一个示例将尝试修复该问题

例3

这看起来比前面的示例更自然

本例中的新功能只是另一个自定义力:将所有父对象“居中”到其子对象水平位置的中间。您可以在“ontick()”函数中轻松找到负责此操作的代码

这看起来更接近您想要的。我并不是说这是一个满足您需求的理想布局。但是,它可以作为一个很好的起点。一旦您了解了所有这些示例,您将能够修改它们,如果您愿意,还可以根据不同的自定义力创建不同的模拟

所以,最后一个例子不是基于物理重力的模拟,但它的效果类似于物理重力。如果你想模拟物理重力,这将需要更多的代码-但如果效果几乎相同,你真的需要它吗


希望这能有所帮助。如果您有问题,需要澄清等,请告诉我。

最简单的方法是调整布局中的“大小”,以便现有“重心”的中心“力位于显示屏底部,而根节点固定在显示屏顶部。但是,您可能需要对参数进行大量调整,才能使事情看起来很好

示例如下:

另一种选择是添加“自定义力”,类似于在中使用的力。该演示中使用的计算细节并不相关,但其思想很简单,在每个
tick()
函数的开头,每个数据点都会在某个方向上稍微调整。如果该方向摆脱了任何其他约束,它将在下一次勾选中被布局的内部计算反作用

示例如下:

var g=0.0005;
函数重力函数(d,i){
如果(d.固定)返回;
//用于修改每个数据对象的位置
//在
var force = d3.layout.force()
    .on("tick", tick)
    .charge(-30)
    .linkDistance(10)
    .gravity(0.005)
    .size([w, 2*h]);
var g = 0.0005;
function gravityFunction(d,i) {
    if (d.fixed) return;
   //used to modify each data object's position
   //at the start of every tick
   var distToGround = h-d.y;
   if (distToGround <= 0) d.y = h; //make "ground" solid
   else d.y += g * (Math.min(distToGround, h/4) ); 
}
function tick() {
    nodeCircles.each(gravityFunction) 
       //adjust each node according to the custom force
        .attr("cx", function (d) {
            return d.x;
        })
        /* etc. */