2013-03-09 261 views
1

我使用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

那麼,爲什麼我需要這個神奇的數字?

回答

2

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