力のレイアウトを使用して、重み付けされていない有向ネットワークを表しています。私のインスピレーションは次の例から来ています: http://bl.ocks.org/mbostock/1153292
サイズの違うノードを作ってみたのですが、少し問題があります。各リンクの矢印を描画するために使用されるマーカーは、円の中心を指します。円が大きすぎると、矢印が完全に隠れてしまいます。
どうすればこれを処理できますか?
力のレイアウトを使用して、重み付けされていない有向ネットワークを表しています。私のインスピレーションは次の例から来ています: http://bl.ocks.org/mbostock/1153292
サイズの違うノードを作ってみたのですが、少し問題があります。各リンクの矢印を描画するために使用されるマーカーは、円の中心を指します。円が大きすぎると、矢印が完全に隠れてしまいます。
どうすればこれを処理できますか?
<line>
の代わりにa を使用する場合<path>
、次のように動作するはずです。現在のソリューションで動作しています。@ɭɘ ɖɵʊɒɼɖ 江戸 ソリューションに基づいています。
tick
イベントリスナーで:
linkElements.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) {
return getTargetNodeCircumferencePoint(d)[0];
})
.attr("y2", function(d) {
return getTargetNodeCircumferencePoint(d)[1];
});
function getTargetNodeCircumferencePoint(d){
var t_radius = d.target.nodeWidth/2; // nodeWidth is just a custom attribute I calculate during the creation of the nodes depending on the node width
var dx = d.target.x - d.source.x;
var dy = d.target.y - d.source.y;
var gamma = Math.atan2(dy,dx); // Math.atan2 returns the angle in the correct quadrant as opposed to Math.atan
var tx = d.target.x - (Math.cos(gamma) * t_radius);
var ty = d.target.y - (Math.sin(gamma) * t_radius);
return [tx,ty];
}
このソリューションは、要素に対応するように変更できると確信して<path>
いますが、試したことはありません。
ノードの半径によってリンクのターゲットをオフセットできます。つまり、コードを調整します
path.attr("d", function(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
});
との値を変更してd.target.x
、d.target.y
半径 ( のようなデータの一部である必要がありますd.target.radius
) を考慮に入れます。つまり、円の半径だけ矢印の端をオフセットします。
ここで私の解決策:
まず、パスの水平軸で角度を計算します ( gamma
)。次に、半径の X コンポーネント ( Math.cos(gamma) * radius
) と Y コンポーネント ( ) を取得します。Math.sin(gamma) * radius
次に、それらのコンポーネントによってパスの端をオフセットします。
function linkArc(d) {
var t_radius = calcRadius(d.target.size);
var s_radius = calcRadius(d.source.size);
var dx = d.target.x - d.source.x;
var dy = d.target.y - d.source.y;
var gamma = Math.atan(dy / dx);
var tx = d.target.x - (Math.cos(gamma) * t_radius);
var ty = d.target.y - (Math.sin(gamma) * t_radius);
var sx = d.source.x - (Math.cos(gamma) * s_radius);
var sy = d.source.y - (Math.sin(gamma) * s_radius);
return "M" + sx + "," + sy + "L" + tx + "," + ty;
}
最初に、私がアークを使用していないことに気付くでしょうが、原則は同じでなければなりません。また、ノードには、円の直径を計算するサイズ プロパティがあります。
最後に、私のマーカーは次のように定義されています。
var arrowsize = 10;
var asHalf = arrowsize / 2;
svg.append("defs").selectAll("marker")
.data(["arrowhead"])
.enter().append("marker")
.attr("id", function (d) {
return d;
})
.attr("viewBox", "0 -5 " + arrowsize + " " + arrowsize)
.attr("refX", arrowsize)
.attr("refY", 0)
.attr("markerWidth", 9)
.attr("markerHeight", 9)
.attr("orient", "auto")
.attr("class", "arrowhead-light")
.append("path")
.attr("d", "M 0," + (asHalf * -1) + " L " + arrowsize + ",0 L 0," + asHalf);
マーカーのすべてのコピーを制御する方法が見つかりません。