12

力のレイアウトを使用して、重み付けされていない有向ネットワークを表しています。私のインスピレーションは次の例から来ています: http://bl.ocks.org/mbostock/1153292

ここに画像の説明を入力

サイズの違うノードを作ってみたのですが、少し問題があります。各リンクの矢印を描画するために使用されるマーカーは、円の中心を指します。円が大きすぎると、矢印が完全に隠れてしまいます。

どうすればこれを処理できますか?

4

5 に答える 5

11

<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>いますが、試したことはありません。

于 2014-11-01T18:17:51.443 に答える
7

ノードの半径によってリンクのターゲットをオフセットできます。つまり、コードを調整します

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.xd.target.y半径 ( のようなデータの一部である必要がありますd.target.radius) を考慮に入れます。つまり、円の半径だけ矢印の端をオフセットします。

于 2013-05-15T15:04:34.940 に答える
1

ここで私の解決策:

まず、パスの水平軸で角度を計算します ( 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);

マーカーのすべてのコピーを制御する方法が見つかりません。

于 2014-06-04T05:45:13.937 に答える