d3 v4:如何使用linkRadial在两点之间绘制链接?

时间:2017-07-06 21:03:09

标签: d3.js

我需要在圆上的点之间手动绘制一些链接,并在所述圆的中心聚集点。我有源,目标点的x,y对,但我不希望它们之间有简单的直线;我想要一条曲线(类似于树形图中的链接)。我可以使用linkHorizontallinkVertical,但它们的切线是恒定的;我想使用linkRadial并将切线作为该特定弧点处的径向线(我也有这个点)。

我不理解linkRadial API;它想要一个角度和一个半径,而不是一个x或y点。如何将我的两个x,y对(以及径向线角度)转换为预期的角度和半径?

1 个答案:

答案 0 :(得分:3)

由于您的数据数组中包含xy位置("我有x和y对的源点和目标点" ),您必须将它们转换为angleradius。让我们看看如何做到这一点。

首先,让我们看一个固定坐标的例子。例如,假设您拥有此数据数组,其中xy位置为:

var data = [{
    source: {y: 150,x: 75
    },
    target: {y: 300,x: 0
    }
}, {
    source: {y: 150,x: 75
    },
    target: {y: 0,x: 0
    }
}, {
    source: {y: 150,x: 75
    },
    target: {y: 150,x: 150
    }
}, ];

使用此链接生成器...

var link = d3.linkHorizontal()
    .x(function(d) {
        return d.y;
    })
    .y(function(d) {
        return d.x;
    });

...你将有一个这样的图表:



var data = [{
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 300,
    x: 0
  }
}, {
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 0,
    x: 0
  }
}, {
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 150,
    x: 150
  }
}, ];

var svg = d3.select("svg");

var link = d3.linkHorizontal()
  .x(function(d) {
    return d.y;
  })
  .y(function(d) {
    return d.x;
  });

svg.selectAll(null)
  .data(data)
  .enter()
  .append("path")
  .attr("fill", "none")
  .attr("stroke", "blue")
  .attr("d", link);

<script src="https://d3js.org/d3.v4.js"></script>
<svg></svg>
&#13;
&#13;
&#13;

我们如何将其转换为可与d3.linkRadial()一起使用的数据集?

一个选项是迭代每个对象,使用基本三角函数填充angleradius属性:

var radialData = data.map(function(d) {
    return {
        source: {
            x: 0,
            y: 0
        },
        target: {
            x: Math.atan2(d.target.y - d.source.y, d.target.x - d.source.x) - Math.PI,
            y: Math.sqrt((d.target.x - d.source.x) * (d.target.x - d.source.x) + (d.target.y - d.source.y) * (d.target.y - d.source.y))
        }
    };
});

然后,使用此链接生成器:

var linkRadial = d3.linkRadial()
    .angle(function(d) {
        console.log(d)
        return d.x;
    })
    .radius(function(d) {
        return d.y;
    });

我们有这个:

&#13;
&#13;
var data = [{
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 300,
    x: 0
  }
}, {
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 0,
    x: 0
  }
}, {
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 150,
    x: 150
  }
}, ];

var svg = d3.select("svg");

var radialData = data.map(function(d) {
  return {
    source: {
      x: 0,
      y: 0
    },
    target: {
      x: Math.atan2(d.target.y - d.source.y, d.target.x - d.source.x) - Math.PI,
      y: Math.sqrt((d.target.x - d.source.x) * (d.target.x - d.source.x) + (d.target.y - d.source.y) * (d.target.y - d.source.y))
    }
  };
});

var g = svg.append("g")
  .attr("transform", "translate(150,75)")

var linkRadial = d3.linkRadial()
  .angle(function(d) {
    return d.x;
  })
  .radius(function(d) {
    return d.y;
  });

g.selectAll(null)
  .data(radialData)
  .enter()
  .append("path")
  .attr("fill", "none")
  .attr("stroke", "red")
  .attr("d", linkRadial);
&#13;
<script src="https://d3js.org/d3.v4.js"></script>
<svg></svg>
&#13;
&#13;
&#13;

现在两个发电机组合在一起,进行比较:

&#13;
&#13;
var data = [{
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 300,
    x: 0
  }
}, {
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 0,
    x: 0
  }
}, {
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 150,
    x: 150
  }
}, ];

var svg = d3.select("svg");

var link = d3.linkHorizontal()
  .x(function(d) {
    return d.y;
  })
  .y(function(d) {
    return d.x;
  });

svg.selectAll(null)
  .data(data)
  .enter()
  .append("path")
  .attr("fill", "none")
  .attr("stroke", "blue")
  .attr("d", link);

var radialData = data.map(function(d) {
  return {
    source: {
      x: 0,
      y: 0
    },
    target: {
      x: Math.atan2(d.target.y - d.source.y, d.target.x - d.source.x) - Math.PI,
      y: Math.sqrt((d.target.x - d.source.x) * (d.target.x - d.source.x) + (d.target.y - d.source.y) * (d.target.y - d.source.y))
    }
  };
});

var g = svg.append("g")
  .attr("transform", "translate(150,75)")

var linkRadial = d3.linkRadial()
  .angle(function(d) {
    return d.x;
  })
  .radius(function(d) {
    return d.y;
  });

g.selectAll(null)
  .data(radialData)
  .enter()
  .append("path")
  .attr("fill", "none")
  .attr("stroke", "red")
  .attr("d", linkRadial);
&#13;
<script src="https://d3js.org/d3.v4.js"></script>
<svg></svg>
&#13;
&#13;
&#13;