2016-11-30 66 views
4

图中的节点链接图中的节点上一个自链接可以做到你需要在同一个节点上绘制多个链接?这里描述了如何利用节点链接图多个自边缘D3

我试图根据存在的自我链接的数量向它添加一个'旋转'。 由于代码链接的例子,我做了以下修改:

function tick() { 
    link.attr("d", function(d) { 
    var x1 = d.source.x, 
    y1 = d.source.y, 
    x2 = d.target.x, 
    y2 = d.target.y, 
    dx = x2 - x1, 
    dy = y2 - y1, 
    dr = Math.sqrt(dx * dx + dy * dy), 

    // Defaults for normal edge. 
    drx = dr, 
    dry = dr, 
    xRotation = 0, // degrees 
    largeArc = 0, // 1 or 0 
    sweep = 1; // 1 or 0 

    // Self edge. 
    if (x1 === x2 && y1 === y2) { 
    // Fiddle with this angle to get loop oriented. 
    var index = getIndexOfDuplicateEdge(); 
    var degree = 360/numberOfDuplicateEdges(); 
    var degreeForIndex = degree * index; 


    xRotation = degreeForIndex; // Previously: -45; 

    // Needs to be 1. 
    largeArc = 1; 

    // Change sweep to change orientation of loop. 
    //sweep = 0; // I also tried to change it based on index % 2 

    // Make drx and dry different to get an ellipse 
    // instead of a circle. 
    drx = 30; 
    dry = 20; 

    // For whatever reason the arc collapses to a point if the beginning 
    // and ending points of the arc are the same, so kludge it. 
    x2 = x2 + 1; 
    y2 = y2 + 1; 
    } 

return "M" + x1 + "," + y1 + "A" + drx + "," + dry + " " + xRotation + "," + largeArc + "," + sweep + " " + x2 + "," + y2; 
}); 

这不会画我的椭圆预期,我无法找到一个方法来处理这个问题。基于SVG from Mozilla,大弧必须是1.扫描可以是0或1,并且会“反射”我的省略号。我可以在90-180之间使用xRotation,扫描0/1将覆盖180度的圈。但是,我没有找到在其他180度位置绘制省略号的方法。

自链接的数量可能会有所不同,我总是希望在省略号之间具有“最佳”分布。

理想的情况下,它应该看起来像:

Self-Linking edges for a node

回答

4

的想法是划分圈成许多部分花瓣的花了。然后计算圆上每个花瓣的起点和终点,并在这些点上拟合一个椭圆。

您可以使用下面的代码片段就实现这一目标:(函数假设你有id为“svgthing”一个SVG元素)

function radtodeg(angle) { 
    return angle * (180/Math.PI); 
} 

function flower(center_x, center_y, num_self_edges, start_angle, end_angle, radius, length) { 

    var angle_sector = end_angle - start_angle; 

    var num_points = num_self_edges * 2; 

    var angle_per_point = angle_sector/num_points; 
    var angle_per_sector = angle_per_point * 2; 

    var str_builder = []; 

    for(var angle = start_angle; angle < end_angle; angle += angle_per_sector) { 
    var start_sector_angle = angle; 
    var end_sector_angle = angle + angle_per_point; 

    var mid_sector_angle = angle + angle_per_point/2; 

    var start_x = center_x + (radius * Math.cos(start_sector_angle)); 
    var start_y = center_y + (radius * Math.sin(start_sector_angle)); 
    var end_x = center_x + (radius * Math.cos(end_sector_angle)); 
    var end_y = center_y + (radius * Math.sin(end_sector_angle)); 

    var mid_x = center_x + (radius * Math.cos(mid_sector_angle)); 
    var mid_y = center_y + (radius * Math.sin(mid_sector_angle)); 

     str_builder.push("<path d='"); 
    str_builder.push("M" + start_x + " " + start_y + ","); 
    str_builder.push("A " + length + " 1 " + radtodeg(mid_sector_angle) + " 0 1 " + end_x + " " + end_y); 
    str_builder.push("'/>\n"); 

    str_builder.push("<circle cx='" + start_x + "' cy='" + start_y + "' r='5' />\n"); 
    str_builder.push("<circle cx='" + end_x + "' cy='" + end_y + "' r='5'/>\n"); 
    str_builder.push("<circle cx='" + mid_x + "' cy='" + mid_y + "' r='5'/>\n"); 
    } 

    str_builder.push("<circle cx='" + center_x + "' cy='" + center_y + "' r='" + radius + "' />\n"); 

    $("#svgthing").html(str_builder.join("")); 
} 

flower(60, 50, 8, 0, 2 * Math.PI, 50, 10); 

的例子通话将产生8个花瓣的花朵。