D3-强制初始化图形后更新参数 [英] D3-Force updating parameters after initializing graph

查看:383
本文介绍了D3-强制初始化图形后更新参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在带有力模块的D3 v4中,初始化图形后如何更新模拟的参数?

In D3 v4 with the force module, how do you update the parameters of the simulation once you have initialized the graph?

更准确地说,当用户单击其有向图时,我试图更改力向图的.forceLink.forceManyBody.

More precisely, I am trying to change the .forceLink and .forceManyBody of the force directed graph when the user clicks one of its nodes.

 var node = svg
    .append("g")
    .attr("class", "gnodes")
    .selectAll(".node")
    .data(graph.nodes)
    .enter()
    .append("g")
    .attr("class", "node")
    .on('dblclick', connectedNodes); //calls for change in simulation parameters

到目前为止,我已经能够通过在connectedNodes函数下复制仿真来对其进行更新:

So far I have been able to update it by duplicating the simulation under the connectedNodes function:

function connectedNodes() {

//new parameters
linkDistance = 5;
fCharge = -10;

//replicates the initial simulation code
simulation = d3.forceSimulation()
    .force("link", d3.forceLink()
        .id(function(d) {return d.id;})
        .distance(linkDistance)
        )
    .force("collide", d3.forceCollide()
        .radius(function(d){return d.r + 10})
        .strength(1)
        )
    .force("charge", d3.forceManyBody()
        .strength(fCharge)
        )
    .force("center", d3.forceCenter(width / 2, height / 2));

simulation.nodes(graph.nodes).on("tick", ticked);

simulation.force("link").links(graph.links);

尽管这有效,但它是非常多余的.有没有一种方法可以用新参数刷新仿真?我已经尝试了以下方法,但是不起作用

Although this works it is very redundant. Is there a way in which the simulation can be refreshed with the new parameters? I have tried the following but it does not work

function connectedNodes() { 

//new parameters
linkDistance = 5;
fCharge = -10;

//restart simulation with new parameters
simulation.restart();
}

推荐答案

您需要参考要更新的力.可以使用以下两种方法之一来完成此操作:

You need a reference to the forces you would like to update. This can be done using either of two ways:

  1. 酷蓝在其 simulation.force() 只是传入了最初注册的部队的名称.如果我们假设是在传递匿名的原地力量的同时创建了仿真,则像这样:

  1. As pointed out by Cool Blue in their comment, you can easily get a reference to the force by calling simulation.force() passing in just the name of the force it was registered with in the first place. If we had, supposedly, created our simulation while passing in an anonymous, in-place force like so:

var simulation = d3.forceSimulation()
  .force("link", d3.forceLink()            // "link" is the name to register the force
    .id(function(d) { return d.id; })
    .distance(linkDistance)
  );

以后可以随时通过其名称获取作用力:

Later on the force can be obtained by its name whenever needed:

var forceLink = simulation.force("link");  // Get the force by its name

我个人而言,我喜欢这种方法,并且在可能的情况下,它会优先于第二种方法,因为我不喜欢周围有很多引用/变量.

Personally, I like this approach and would prefer it over the second one, whenever possible, because I do not like having to many references / variables around.

在创建力时保留对其的引用.

Keep a reference to the force when creating it.

var forceLink = d3.forceLink()      // Keep a reference to the force
  .id(function(d) { return d.id; })
  .distance(linkDistance);

var simulation = d3.forceSimulation()
  .force("link", forceLink )        // Pass the reference when creating the simulation

无论选择哪种方式,您都可以通过

No matter, which way you chose, you may then update your force by doing something like

linkDistance += 10;
forceLink.distance(linkDistance);

一旦计算下一个刻度,它将考虑新值.如果模拟已经停止或您只想再次加热,则可以致电

This will take the new value into account once the next tick is calculated. If the simulation has already come to a stop or you just want to heat it up again you may call

simulation.alpha(1).restart();

我设置了一个示例,当您将鼠标悬停在SVG上时,将显示这些实时更新.这将更新linkDistance并重新开始强制布局.

I have set up an example which shows these live updates when you hover over the SVG. This will update the linkDistance and restart the force layout.

这篇关于D3-强制初始化图形后更新参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆