D3.js v4/v5 force simulation ノード相互作用 – サンプル

2018-02-02

D3.jsのforceSimulationのプログラムデモです(v4/v5対応)。リンクなしバージョンです。ノード間の相互作用を説明します。

ノード(丸いやつ)をドラックしてください。

サンプルコード

解説

1. 描画用のデータ準備

まず、ノード用のデータ(nodesData)を準備します。forceSimulationによりnodesDataのx、y座標が更新されますが、最初にx、yを定義しておけば初期位置として設定できます。半径をノードごとに変えたいのでrを変数にして定義しておきます。

2. svg要素を配置

ノードのsvg要素を配置していきます。call( )でドラッグ時のイベント関数を登録しています。
また、

の部分で、ノードごとに異なる半径を割り当てています。

3. forceSimulation設定

forceSimulationでは下記の相互作用を設定することができます。

  • "link"      : ノード間をつなぐリンクの作用力 (今回は省略、こちらを参照)
  • "collide"  : ノード間の接触反発力
  • "charge" : ノード間のクーロン力(非接触作用力)
  • "x", "y"   : 位置に基づく場の力
  • "center" : 全てのノードの質量中心
  • "r"         : ラジアルフォース(こちらを参照)

link以外の部分を詳細に見ていきます。

"collide" : ノード間の接触反発力

radius simulationするノードの半径を設定します。デフォルトは1。今回は変数にfunction(d) { return d.r; }を設定し、nodesDataで定義した半径rを割り当てます。半径の変数のみを関数にしいますが、他のパラメータもすべて関数を設定可能です。
strength オーバーラップするノード間の反発力です。0.0~1.0の小数点で設定します。デフォルトは0.7。
iterations simulationの反復回数。反復回数を増やすと計算が大幅に安定し、ノードの重なりが回避されやすくなりますが、計算時間が増加します。デフォルトは1。

"charge" : ノード間のクーロン力(非接触作用力)

strength 正の値を指定すると重力と同様にノードが互いに引き寄せられ、負の値を指定すると静電気と同様にノードが互いに反発します。値の大きさで力の大きさを設定します。デフォルトは-30。
theta 計算の近時の精度を決める定数。全ての粒子間のクーロン力を計算すると時間がかかるため、遠くにあるノード塊として計算する(Barnes-Hut近似)ことで高速化しています。デフォルトは0.9。(今回は未設定)
distanceMin クーロン力を計算する最小距離。二つのノードが重なると距離が0になり、力が無限大になることを回避します。デフォルトは1。(今回は未設定)
distanceMax ノード間の最大距離を設定します。指定されていない場合は、現在の最大距離を返す。デフォルトは無限大。最大距離を指定すると、パフォーマンスが向上します。(今回は未設定)

"x", "y"   : 位置に基づく場の力

strength 場の力の大きさを表す指標で、計算1ステップで指定した位置にどのぐらい戻るかを決める係数です。0.1であれば指定した位置に向かって計算1ステップで10%移動します。0.0~1.0が推奨値で、デフォルトは0.1。
x 場の力の中心x座標です。デフォルトは0。
y 場の力の中心y座標です。デフォルトは0。

"center" : 全てのノードの質量中心

d3.forceCenter(x, y) 全てのノードの質量中心の座標です。ビューポートの中央に描画を保持するのに役立ちます。他の作用力とは異なり、ノード間の相対位置を変更しません。

4. forceSimulation 描画更新用関数

シミュレーションのステップごとに呼び出される関数です。svg要素を動かすために計算結果をsvg要素の位置に反映します。

5. forceSimulation 描画更新用関数

ドラッグ時のイベント関数です。ノード用のデータにfx, fyが定義されている場合、そのノードの座標が固定されます。ドラッグ中にマウスと動作を連動させるため、ドラッグ開始時にドラック要素の位置を固定し、ドラッグ中はマウス座標(d3.event.x, d3.event.y)を反映して、ドラッグ終了時に固定を解除(nullを代入)します。
また、simulationは時間がたつと停止する仕様になっているので、ドラッグ開始時にsimulationがactiveでない場合はリスタートさせます。このときに設定しているalphaTargetは、シミュレーションを滑らかに繋げるための係数で0~1の値を設定でき、低い値の方が滑らかになります。

まとめ

ここでは、ノード相互作用の詳細をまとめました。次にリンクによる相互作用を見ていきたいと思います。