私は Phrogz とは少し異なるアプローチを取りました。パスのマーカーを削除しようとしましたが、代わりに、円弧の中点に行き、ストロークが見えない新しいパスを使用して描画しました。中点の計算は少し面倒なので、円弧の特性を変更したい場合は、Phrogz のアプローチまたはハイブリッドを使用する方がよいかもしれません。
この場合、トリガーはそれほど悪くはありません。よく見ると、リンクを生成するために使用される円弧が、同じ半径とノード間の距離を持つ円からのものであることがわかるからです。したがって、正三角形があり、実際に行う必要があるのは、リンク ライン セグメントの中点から弧の中点までの距離を計算することだけです。
説明するには図が必要だと思います:
したがって、三角形 ABC は正三角形で、EC は AB を二等分します。A と B の座標があるので、M を見つけるのは簡単です (座標の平均)。つまり、A から B への勾配 (デルタ y / デルタ x) もわかっているため、M から E への勾配は負の逆数になります。M と E への勾配がわかれば、あとはあとどれくらいかを知る必要があるだけです。
これを行うには、ACM が 30-60-90 三角形であるという事実を使用します。
|CM| = sqrt(3) * |AM|
しかし|午前| = |AB| / 2 および |CE| = |AB|
そう
|私| = |AB| -sqrt(3) * |AB| / 2
この長さが意味を成すためには、勾配ベクトルの長さで正規化する必要があります。これは、円の半径と同じであることが既にわかっています。
とにかく、すべてをまとめると、次のようになります。
var markerPath = svg.append("svg:g").selectAll("path.marker")
.data(force.links())
.enter().append("svg:path")
.attr("class", function(d) { return "marker_only " + d.type; })
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
... later in the tick handler
markerPath.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);
// We know the center of the arc will be some distance perpendicular from the
// link segment's midpoint. The midpoint is computed as:
var endX = (d.target.x + d.source.x) / 2;
var endY = (d.target.y + d.source.y) / 2;
// Notice that the paths are the arcs generated by a circle whose
// radius is the same as the distance between the nodes. This simplifies the
// trig as we can simply apply the 30-60-90 triangle rule to find the difference
// between the radius and the distance to the segment midpoint from the circle
// center.
var len = dr - ((dr/2) * Math.sqrt(3));
// Remember that is we have a line's slope then the perpendicular slope is the
// negative inverse.
endX = endX + (dy * len/dr);
endY = endY + (-dx * len/dr);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + endX + "," + endY;
});
ここでチェックしてください。マーカー パスのパス css は透明な赤に設定されていることに注意してください。通常は、線を非表示にするためにストロークを「なし」に設定します。