D3js - 圆形位置与圆弧或曲线路径的半径

问题描述:

我使用D3.js创建了太阳系的数据可视化。 这样做的时候,我在设置一个圆形元素的x,y位置和一个圆形元素或曲线路径元素的半径时,发现了一个奇怪的不一致性。 要放置行星下来,我做的:D3js - 圆形位置与圆弧或曲线路径的半径

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) + ")"; }); 

这里是demostrating这个(平移和缩放如果你需要一个更好的视野)的jsfiddles:

Solar System with Magic Number

Solar System without Magic Number

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

角度在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; });