ノードをd3 forceシミュレーション(バージョン4では!)に1つずつ追加しようとしていますが、作成された後にシミュレーションによって進化していないように見えるもの。d3 v4動的に追加されたノードに作用する力
現在シミュレーションは、その後、1つのノードの機能を割り当てて、てaddNodeを二回、さらに2つのノードを追加すると呼ばれています。それぞれがシミュレーションに追加され、円と線が描画され、カーソルイベントが1つずつ追加されます。
ノードがクリックされたとき、
次に、新しいノードを、(技術的に第一及び第二のノードは最初のみにaddNode第二に呼び出されたときに設定されているように、同時に行われる)接続しますカーソルの下のものまで、作成する必要があります。このノードは、他のシミュレーションのようにシミュレーションの力の下で進化するはずです。
しかし、 1ながらまたは2つのノードが、後にノードがシミュレーションの下で進化していないようです、罰金を作成しているように見えます。具体的には、ノード間にある程度のスペースを確保する必要のある多体力は機能していないようです。
私の直感は、(以前の問題がいくつかsimulation.stopとsimulation.restartを追加することで解決された新しいノードが追加されていたすべての時間をコマンド)のノードは、シミュレーションのチェックが入っ機能のために都合の悪い時に追加されていることですが、新しいボディが追加されるたびに理論上はシミュレーションを一時停止する必要があります。
これは、d3 v4でノードを動的に追加する正しい実装ですか、またはマングルされたメソッドを強調表示するだけの問題ですか? This以前の回答新しいエントリをマージする必要があることを認識するのに役立ちましたが、そこでは力がうまく機能しているようです。
var w = 250;
var h = 250;
var svg = d3.select("body").append("svg");
svg.attr('width', w)
.attr('height', h);
// ensures links sit beneath nodes
svg.append("g").attr("id", "lnks")
svg.append("g").attr("id", "nds")
function new_node(id) {
this.id = id;
this.x = w/2;
this.y = h/2;
}
function new_link(source, target) {
this.source = source;
this.target = target;
}
var nodes = [];
var links = [];
var node;
var circles;
var link;
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().distance(80).id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody().strength(-1000))
.force("xPos", d3.forceX(w/2))
.force("yPos", d3.forceY(h/2))
.on('tick', ticked);
simulation.stop();
var newNode = new new_node(0);
nodes.push(newNode);
for (var i = 1; i < 3; i++) {
if (i == 3) continue;
addNode(0, i)
}
function addNode(rootId, newId) {
var newNode = new new_node(newId);
nodes.push(newNode);
var newLink = new new_link(rootId, newId);
links.push(newLink);
//adds newest link and draws it
link = svg.select("#lnks").selectAll(".link")
.data(links)
var linkEnter = link
.enter().append("line")
.attr("class", "link");
link = linkEnter.merge(link);
//adds newest node
node = svg.select("#nds").selectAll(".node")
.data(nodes)
var nodeEnter = node
.enter().append("g")
.attr("class", "node");
//draws circle on newest node
var circlesEnter = nodeEnter.append('circle')
node = nodeEnter.merge(node);
circles = d3.selectAll('circle');
simulation.stop();
simulation.nodes(nodes);
simulation.force("link")
.links(links);
restartSim();
}
//starts up the simulation and sets up the way the leaves react to interaction
function restartSim() {
simulation.restart();
circles.on('click', function(d, i) {
addNode(i, nodes.length)
})
}
function ticked() {
link
.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
.link {
stroke: #bbb;
}
.node circle {
pointer-events: all;
fill: black;
stroke-width: 0px;
r: 20px
}
h1 {
color: white;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
コードもここcodepenに:名前として http://codepen.io/zpenoyre/pen/kkxBRW?editors=0010
:ここ
は、更新されたコードペンです。ここでアルファが何をしているのかを理解する簡単な方法はありますか? 「Reheating」は私には直感的ではないようで、[d3 API](https://github.com/d3/d3-force/blob/master/README.md#simulation_alpha)は私にとっては意味がない件名に。 – Zephyr驚くべきことに、シミュレーションを効果的に行うことはできませんでしたが、よく見ています。シミュレーションの計算量を減らしたいが、セットアップを変更するたびにシミュレーションを再開する必要があります。ありがとう! – Zephyr
@Zephyr 2番目のコメントから、おそらくそれが得られます。しかし、あなたや他の誰かのために 'simulation.alphaTarget'コミットのための良い追加情報があります:(https://github.com/d3/d3-force/commit/8a2c8590bb879c70eb2e10264b41d0200c887be9)"これはシミュレーションでは、 シミュレーションをスムーズに目的の値に向かって補間します。デフォルトでは、 の目標値は0で、シミュレーションが冷たくなりますが、 に設定することで、ドラッグ操作の間など、それを使用して シミュレーションヒートを得ることもできます。 – ibgib