Get arrowheads to point at outer edge of node in D3

后端 未结 2 504
小蘑菇
小蘑菇 2020-12-05 14:46

I\'m new to D3 and I\'m trying to create an interactive network visualization. I\'ve copied large parts of this example, but I have changed the curved lines to straight one

相关标签:
2条回答
  • 2020-12-05 15:42

    Thanks Lars Kotthoff, I got this to work following the advice from the other question! First I switched from using lines to paths. I don't think I actually had to do that, but it made it easier to follow the other examples I was looking at because they used paths.

    Then, I added a "radius" field to my nodes. I just did this when I set the radius attribute, by adding it as an actual field rather than returning the value immediately:

    var circle = svg.append("svg:g").selectAll("circle")
                        .data(force.nodes())
                        .enter().append("svg:circle")
                        .attr("r", function(d) {
                            if (d.logic != null) {
                                d.radius = 5;
                            } else {
                                d.radius = node_scale(d.classSize);
                            }
                            return d.radius;
    

    I then edited my tick() function to take this radius into account. This required a bit of simple geometry...

    function tick(e) {
    
            path.attr("d", function(d) {
                // Total difference in x and y from source to target
                diffX = d.target.x - d.source.x;
                diffY = d.target.y - d.source.y;
    
                // Length of path from center of source node to center of target node
                pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY));
    
                // x and y distances from center to outside edge of target node
                offsetX = (diffX * d.target.radius) / pathLength;
                offsetY = (diffY * d.target.radius) / pathLength;
    
                return "M" + d.source.x + "," + d.source.y + "L" + (d.target.x - offsetX) + "," + (d.target.y - offsetY);
            });
    

    Basically, the triangle formed by the path, it's total x change (diffX), and it's total y change (diffY) is a similar triangle to that formed by the segment of the path inside the target node (i.e. the node radius), the x change inside the target node (offsetX), and the y change inside the target node (offsetY). This means that the ratio of the target node radius to the total path length is equal to the ratio of offsetX to diffX and to the ratio of offsetY to diffY.

    I also changed the refX value to 10 for the arrows. I'm not sure why that was necessary but now it seems to work!

    0 讨论(0)
  • 2020-12-05 15:43

    I answered the same question over here. The answer uses vector math, it's quite useful for other calculations as well.

    0 讨论(0)
提交回复
热议问题