1

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は次のとおりです(より良いビューが必要な場合は、パンとズームしてください):

マジックナンバーのある太陽系

マジックナンバーのない太陽系

では、なぜこのマジック ナンバーが必要なのでしょうか。

4

1 に答える 1

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)

2番目の魔法数(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; });
于 2013-03-09T23:48:34.340 に答える