admin管理员组

文章数量:1335430

I have this D3 jsfiddle that produces following diagram:

The only thing that bothers me about this diagram is that if there is only one link between two nodes, it is drawn as a curve. I think it would be much better if such links were just straight lines (arrow would be fine). Let's say between Microsoft and Amazon should be just a straight line (with arrow). The same between Oracle and Google, Sony and LG, etc.

How to achieve this?

I have this D3 jsfiddle that produces following diagram:

The only thing that bothers me about this diagram is that if there is only one link between two nodes, it is drawn as a curve. I think it would be much better if such links were just straight lines (arrow would be fine). Let's say between Microsoft and Amazon should be just a straight line (with arrow). The same between Oracle and Google, Sony and LG, etc.

How to achieve this?

Share Improve this question edited Jan 22, 2015 at 21:28 VividD asked Jan 22, 2015 at 21:18 VividDVividD 10.5k8 gold badges66 silver badges112 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

It's very easy. In your linkArc(d) method, just set the dr parameter to 0 if there is only 1 child, or the default one, if there are more. This way there won't be any curve between the nodes.

The first step though, will be to determine how many neighbours there are. A simple way would be like the following just after you define the nodes from the links, though it is not optimal.

links.forEach(function(d) {
    if (nodes[d.source.name].children==undefined) {
        nodes[d.source.name].children=0;
    }
    nodes[d.source.name].children++
});

Once you do that, you can adjust the curve of the line as follows:

function linkArc(d) {
  var dx = d.target.x - d.source.x,
      dy = d.target.y - d.source.y,
      dr = (nodes[d.target.name].children>1 & nodes[d.source.name].children>1)?Math.sqrt(dx * dx + dy * dy):0;
  return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}

The result will be like this:

I am sure that there are much better ways to tackle this, but it is a start. Hope this helps.

This is based on @Nikos answer:

links.forEach(function(d) {
    d.straight = 1;
    links.forEach(function(d1) {
        if ((d.source == d1.target) && (d1.source == d.target))
            d.straight = 0;
    });
});

and

function linkArc(d) {
  var dx = d.target.x - d.source.x,
      dy = d.target.y - d.source.y,
      dr = (d.straight == 0)?Math.sqrt(dx * dx + dy * dy):0;
  return "M" + d.source.x + "," + d.source.y +
      "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}

yield to correct diagram: (with respect to straightness of connections)

jsfiddle

本文标签: javascriptD3 force layout Straight line instead of curve for links (but only for some links)Stack Overflow