【问题标题】:D3js - Circle position vs radius of circle or curved pathD3js - 圆位置与圆或曲线路径的半径
【发布时间】:2013-03-09 21:54:45
【问题描述】:

我使用 D3.js 创建了太阳系的数据可视化。 这样做时,我注意到在设置圆形元素的 x、y 位置和圆形元素或曲线路径元素的半径时出现了奇怪的不一致。 为了把行星放下,我这样做:

planetEnter.append("circle")
    .attr("r", function (d) {
         return planetScale(d.radius); })
    .attr("class", "body")
    .attr("fill", "url(#gradePlanet)")
    .attr("filter", "url(#glowPlanet)")
    .attr("transform", function (d) {
         // Position of planet in relation to the sun at (0,0)
         // x and y are linear scales
         return "translate(" + x(d.orbital_radius) + ", " + y(0) + "), scale(.05)"; });

现在要创建轨道线,我这样做:

var orbital_arc = d3.svg.arc()
    .startAngle(0)
    .endAngle(6.28318531) // 360 degrees
    .innerRadius(function (d) {
        return x(d.orbital_radius); }) 
    .outerRadius(function (d) {
        return x(d.orbital_radius); });

现在您会认为这会起作用,并且圆弧的半径会与行星的位置相匹配,但事实并非如此。半径最终要大得多。作为补偿,我通过反复试验找到了这个神奇的数字:

var orbital_arc = d3.svg.arc()
    .startAngle(0)
    .endAngle(6.28318531) // 360 degrees
    .innerRadius(function (d) {
        return x(d.orbital_radius) - 470; }) // Magic number.
    .outerRadius(function (d) {
        return x(d.orbital_radius) - 470; }); // Magic number.

这个数字始终适用于每条轨道线,我不知道为什么。 而且不仅仅是路径元素,圆的半径最终也会更大:

planetEnter.append("circle")
    .attr("r", function (d) {
        return x(d.orbital_radius); })
    .attr("class", "body")
    .attr("transform", function (d) {
        return "translate(" + x(0) + ", " + y(0) + ")"; });

这里是演示这个的 jsfiddles(如果您需要更好的视图,可以平移和缩放):

Solar System with Magic Number

Solar System without Magic Number

那么为什么我需要这个神奇的数字呢?

【问题讨论】:

    标签: svg d3.js


    【解决方案1】:

    D3 中的角度是以弧度设置的,所以你可以有一个函数...

    function degreesToRadians(degrees) {
      return degrees * (Math.PI/180);
    }
    

    但是你总是使用圆圈,所以这更优雅地简单地通过......

    var tau = Math.PI * 2; //this is your first magic number
    var orbital_arc = d3.svg.arc()
        .startAngle(0)
        .endAngle(tau)
    

    至于第二个幻数(470)它是你宽度的一半,所以把它们放在一起你就可以做到......

    var tau = Math.PI * 2; //this is your first magic number
    var orbital_arc = d3.svg.arc()
        .startAngle(0)
        .endAngle(tau)
        .innerRadius(function (d) { return x(d.orbital_radius) - width/2; })
        .outerRadius(function (d) { return x(d.orbital_radius) - width/2; });
    

    【讨论】: