用箭头连接可变半径的节点 [英] linking nodes of variable radius with arrows

查看:15
本文介绍了用箭头连接可变半径的节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些不同半径的圆/节点,我必须将它们与具有箭头末端的路径连接起来.

I have some circles/nodes of different radius and I have to connect them with paths having arrow ends.

这是标记的代码:

svg.append("svg:defs").selectAll("marker")
    .data(["default"])
  .enter().append("svg:marker")
    .attr("id", String)
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 5)
    .attr("refY", -1.5)
    .attr("markerWidth", 10)
    .attr("markerHeight", 10)
    .attr("orient", "auto")
    .append("svg:path")
    .attr("d", "M1,-5L10,0L0,5");  

我已经将圆的半径存储在一个数组中.这是屏幕截图:

I have stored the radius of circles in an array. Here's the screen shot:

箭头实际上在圆圈的内部".如何让箭头位于圆圈的表面?

The arrow is actually "inside" the circles. How do I get the arrows to be at the surface of the circles?

推荐答案

这是一个老问题,但如果您希望箭头位于节点的边缘而不是在节点的顶部或下方,这里是我的解决方案.我的方法也是绘制连接节点的路径,使端点位于节点的边缘而不是节点的中心.从移动专利诉讼示例开始 (http://bl.ocks.org/mbostock/1153292),我将 linkArc 方法替换为:

This is an old question, but here is my solution if you want your arrowheads to be at the edge of your nodes instead of on top of or beneath them. My approach was also to draw the path connecting the nodes such that the end points were on the nodes' edges rather than at the nodes' centers. Starting from the Mobile Patent Suits example (http://bl.ocks.org/mbostock/1153292), I replaced the linkArc method with:

function linkArc(d) {
    var sourceX = d.source.x;
    var sourceY = d.source.y;
    var targetX = d.target.x;
    var targetY = d.target.y;

    var theta = Math.atan((targetX - sourceX) / (targetY - sourceY));
    var phi = Math.atan((targetY - sourceY) / (targetX - sourceX));

    var sinTheta = d.source.r * Math.sin(theta);
    var cosTheta = d.source.r * Math.cos(theta);
    var sinPhi = d.target.r * Math.sin(phi);
    var cosPhi = d.target.r * Math.cos(phi);

    // Set the position of the link's end point at the source node
    // such that it is on the edge closest to the target node
    if (d.target.y > d.source.y) {
        sourceX = sourceX + sinTheta;
        sourceY = sourceY + cosTheta;
    }
    else {
        sourceX = sourceX - sinTheta;
        sourceY = sourceY - cosTheta;
    }

    // Set the position of the link's end point at the target node
    // such that it is on the edge closest to the source node
    if (d.source.x > d.target.x) {
        targetX = targetX + cosPhi;
        targetY = targetY + sinPhi;    
    }
    else {
        targetX = targetX - cosPhi;
        targetY = targetY - sinPhi;   
    }

    // Draw an arc between the two calculated points
    var dx = targetX - sourceX,
        dy = targetY - sourceY,
        dr = Math.sqrt(dx * dx + dy * dy);
    return "M" + sourceX + "," + sourceY + "A" + dr + "," + dr + " 0 0,1 " + targetX + "," + targetY;
}

请注意,此代码要求节点数据中包含r"或半径属性.为了将箭头的点放置在正确的位置,我更改了 refX 和 refY 属性,使箭头的点位于节点的边缘:

Note that this code expects an "r," or radius, attribute to be in the node data. To place the points of the arrows at the correct positions, I changed the refX and refY attributes so that the point of the arrow was at the edge of the node:

svg.append("defs").selectAll("marker")
    .data(["suit", "licensing", "resolved"])
  .enter().append("marker")
    .attr("id", function(d) { return d; })
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 10)
    .attr("refY", 0)
    .attr("markerWidth", 6)
    .attr("markerHeight", 6)
    .attr("orient", "auto")
  .append("path")
    .attr("d", "M0,-5L10,0L0,5");

这篇关于用箭头连接可变半径的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆