如何停止d3力图布局模拟? [英] How to stop a d3 force graph layout simulation?

查看:500
本文介绍了如何停止d3力图布局模拟?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一旦你d3.layout.force().... start()在D3中的强制布局模拟,它继续与一个活动事件。



我想设置一个5秒的超时,让图形强制布局模拟成型和停止(调用.stop()或alpha(0)停止,但是一旦我拖动一个节点,模拟再次开始。



下面的代码也可以从。


Once you d3.layout.force()....start() a force layout simulation in D3, it keeps on going with also an active event.

I want to set a timeout of 5 seconds to let the graph force layout simulation take shape and stop ( calling .stop() or alpha(0). This works to stop, but as soon as I drag a node the simulation starts again.

The following code, also on easily testable from jsfiddle, shows at the last line that the stop() will be issued and the simulation immediately stops, but as soon as you drag any node, the simulation starts again. I think this is hardcoded in the force-drag. Is there a way to disable/unregister this ?

var svgContainer = d3.select("#svgContainer");

var element0a = svgContainer.append("g").attr("class","node").attr("transform","translate(100,100)");
var element0b = element0a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","red");

var element1a = svgContainer.append("g").attr("class","node").attr("transform","translate(100,200)");
var element1b = element1a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","green");

var element2a = svgContainer.append("g").attr("class","node").attr("transform","translate(100,300)");
var element2b = element2a.append("rect").attr("x",0).attr("y",0).attr("width",20).attr("height",10).attr("fill","blue");

var nodeArray = new Array();
nodeArray[0] = { id : "000", label : "label 000", ui : element0a };
nodeArray[1] = { id : "001", label : "label 001", ui : element1a };
nodeArray[2] = { id : "002", label : "label 002", ui : element2a };

var linkArray = new Array();

var force = self.force = d3.layout.force()
    .nodes(nodeArray)
    .links(linkArray)
    .gravity(.05)
    .distance(80)
    .charge(-100)
    .size([600, 600])
    .start();

var node = svgContainer.selectAll("g.node")
    .data(nodeArray)
    .call(force.drag);


force.on("tick", function() {
      node.attr("transform", function(d) {return "translate(" + d.x + "," + d.y + ")";});
    });

// HERE !!!! Without the stop() the simulation goes fine. With the stop() the simulation will immediately stop, but will continue as soon as you drap something. I want the simulation to never start again. 

force.stop();

This is a screenshot of the example:

解决方案

The simulation is restarted in the function that is called when a node is dragged internally. You can however overwrite this behaviour. The event name is "drag.force" and you can access it through force.drag. Instead of the usual behaviour, you can modify the coordinates directly without restarting the simulation like this:

var node...
  .call(force.drag().on("drag.force", function() {
    d3.select(this).attr("transform", "translate(" + d3.event.x + "," + d3.event.y + ")");
  }));

This corresponds to the normal drag behavior. Before you do this, it is advisable to stop the simulation to prevent the drag event and force ticks from interfering. Simply call force.stop() at the beginning of your modified event handler.

Finally you'll need to reset the origin for the drag events, otherwise you'll notice that dragged elements "jump" back to their original position when you drag them again. This is done in similar fashion to modifying the event handler. You simply get the current translation and return the coordinates in the expected format.

var node...
  .call(force.drag().origin(function() {
    var t = d3.transform(d3.select(this).attr("transform")).translate;
    return {x: t[0], y: t[1]};
  }));

The complete code is in the updated jsfiddle here.

这篇关于如何停止d3力图布局模拟?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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