2013-07-19 9 views
9

私はd3.jsを使って視覚化しているデータセットを持っています。この時点でd3.jsのバブルを強制的/重力ベースのレイアウトに変換する

var xp = d3.scale.log().domain([300, 1e5]).range([0, width]), 
    yp = d3.scale.linear().domain([10, 85]).range([height, 0]), 
    radiusp = d3.scale.sqrt().domain([0, 5e8]).range([0, 40]), 
    colorp = d3.scale.category10(); 

次のようにXP、YP、colorpとradiuspが定義されている
var dot = svg.selectAll("g") 
      .data(data) 
      .enter() 
      .append("g"); 

dot.append("circle") 
    .attr("class", "dot") 
    .attr("cx", function(d) { return xp(x(d)); }) 
    .attr("cy", function(d) { return yp(y(d)); }) 
    .style("fill", function(d) { return colorp(color(d)); }) 
    .attr("r", function(d) { return radiusp(radius(d)*2000000); }); 

dot.append("text") 
    .attr("x", function(d) { return xp(x(d)); }) 
    .attr("y", function(d) { return yp(y(d)); }) 
    .text(function(d) { return d.name; }) 

:私は次のように気泡の構成であり、気泡の形でデータ点を表していバブルのサイズは基本的にradiuspから来ており、colorはcolorpで定義されていますが、バブルはその位置に静的に表示されます(positionはxpとypによって定義されます)。

今私は、この例のように、正確にそれらを示しています: http://bl.ocks.org/mbostock/4063269

enter image description here

私はこのフォームでそれらを表示することで必要なもの: http://jsfiddle.net/andycooper/PcjUR/1/

enter image description here

それは:それらは重力機能を使用して詰め込まれていて、ある程度の電荷を持っていて、ある程度ドラッグされ弾かれていなければなりません。私はd3.layout.force()を通る方法があるが、これを実際にこのようなものに統合することはできないことがわかります。私に正しい道筋や実際の例やヒントを教えていただければ本当に感謝しています。ありがとうございました。

+0

まだ回答がありませんか? – user2480542

+0

'd3.layout.force()に統合中に直面している問題は何ですか – user568109

+0

問題はd3.layoutです。force()は自動的にcxとcy座標を定義しており、アプローチと実装方法を正確に把握することはできません。気泡の位置を強制するxpとyp変数を削除しても、それを達成することはできません。最初は、これらのバブルの強制レイアウトを実装しようとしましたが、失敗しました。 : -/ – user2480542

答えて

2

私はあなたがほとんどそこにいたと思うが、あなたのdot変数の仕様は最善のものではない。私はこのようにそれを変換します:丸がプロットされた後

var dot = svg.selectAll(".dot") 
     .data(data) 
     .enter() 

その後、何を行うことは、あなたが、forceレイアウトを作成し、作成したノードでそれをインスタンス化することで、その後、on("tick")メソッドを追加し、 startレイアウト。例は以下の通りです:

var force = d3.layout.force().nodes(data).size([width, height]) 
      .gravity(0) 
      .charge(0) 
      .on("tick", function(e){ 
       dot 
       .each(gravity(.2 * e.alpha)) 
        .each(collide(.5)) 
        .attr("cx", function (d) {return d.x;}) 
        .attr("cy", function (d) {return d.y;}); 
      }) 
      .start(); 

完全な答えを持っているために、私は(調整変数名で)も

function gravity(alpha) { 
     return function (d) { 
      d.y += (d.cy - d.y) * alpha; 
      d.x += (d.cx - d.x) * alpha; 
     }; 
    } 

    function collide(alpha) { 
     var padding = 6 
     var quadtree = d3.geom.quadtree(dot); 
     return function (d) { 
      var r = d.r + radiusp.domain()[1] + padding, 
       nx1 = d.x - r, 
       nx2 = d.x + r, 
       ny1 = d.y - r, 
       ny2 = d.y + r; 
      quadtree.visit(function (quad, x1, y1, x2, y2) { 
       if (quad.point && (quad.point !== d)) { 
        var x = d.x - quad.point.x, 
         y = d.y - quad.point.y, 
         l = Math.sqrt(x * x + y * y), 
         r = d.r + quad.point.r + (d.color !== quad.point.color) * padding; 
        if (l < r) { 
         l = (l - r)/l * alpha; 
         d.x -= x *= l; 
         d.y -= y *= l; 
         quad.point.x += x; 
         quad.point.y += y; 
        } 
       } 
       return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; 
      }); 
     }; 
    } 

をごフィドルからgravitycollideメソッドを追加します私はあなたが持っていた問題を考えます残念なことに作業していなかった各サークルの要素にg要素に強制レイアウトを適用していた可能性があります。私はこれがあなたの進め方を知ってくれることを願っています。 dot宣言の最後の行には、各サークルにg要素が追加されていましたが、処理が少し難しかったです。

ありがとうございました。

PS私はあなたのdataxy、およびr属性はxy、およびradiusが含まれていることを前提としています。

関連する問題