36

私は D3 を初めて使用し、フォース ディレクテッド レイアウトの境界を設定するのに問題があります。私が望むものを(例から)なんとかまとめましたが、グラフを含める必要があります。ティック関数では、変換/変換によってグラフが正しく表示されますが、cx と cy を Math.max/min で使用すると (コメント付きのコードを参照)、行が適切に含まれている間にノードが左上隅に固定されます。

これが私が下に持っているものです...私は何を間違っていますか??

var w=960, h=500, r=8,  z = d3.scale.category20();

var color = d3.scale.category20();

var force = d3.layout.force()
       .linkDistance( function(d) { return (d.value*180) } )
       .linkStrength( function(d) { return (1/(1+d.value)) } )
       .charge(-1000)
       //.gravity(.08)
       .size([w, h]);

var vis = d3.select("#chart").append("svg:svg")
       .attr("width", w)
       .attr("height", h)
       .append("svg:g")
       .attr("transform", "translate(" + w / 4 + "," + h / 3 + ")");

vis.append("svg:rect")
   .attr("width", w)
   .attr("height", h)
   .style("stroke", "#000");


d3.json("miserables.json", function(json) {

       var link = vis.selectAll("line.link")
               .data(json.links);

       link.enter().append("svg:line")
               .attr("class", "link")
               .attr("x1", function(d) { return d.source.x; })
               .attr("y1", function(d) { return d.source.y; })
               .attr("x2", function(d) { return d.source.x; })
               .attr("y2", function(d) { return d.source.y; })
               .style("stroke-width", function(d) { return (1/(1+d.value))*5 });

       var node = vis.selectAll("g.node")
               .data(json.nodes);

       var nodeEnter = node.enter().append("svg:g")
               .attr("class", "node")
               .on("mouseover", fade(.1))
               .on("mouseout", fade(1))
               .call(force.drag);

       nodeEnter.append("svg:circle")
               .attr("r", r)
               .style("fill", function(d) { return z(d.group); })
               .style("stroke", function(d) { return
d3.rgb(z(d.group)).darker(); });

       nodeEnter.append("svg:text")
               .attr("text-anchor", "middle")
               .attr("dy", ".35em")
               .text(function(d) { return d.name; });

       force
       .nodes(json.nodes)
       .links(json.links)
       .on("tick", tick)
       .start();

       function tick() {

       // This works
               node.attr("transform", function(d) { return "translate(" + d.x + ","
+ d.y + ")"; });

       // This contains the lines within the boundary, but the nodes are
stuck in the top left corner
               //node.attr("cx", function(d) { return d.x = Math.max(r, Math.min(w
- r, d.x)); })
               //      .attr("cy", function(d) { return d.y = Math.max(r, Math.min(h -
r, d.y)); });

       link.attr("x1", function(d) { return d.source.x; })
               .attr("y1", function(d) { return d.source.y; })
               .attr("x2", function(d) { return d.target.x; })
               .attr("y2", function(d) { return d.target.y; });
       }

       var linkedByIndex = {};

   json.links.forEach(function(d) {
       linkedByIndex[d.source.index + "," + d.target.index] = 1;
   });

       function isConnected(a, b) {
       return linkedByIndex[a.index + "," + b.index] ||
linkedByIndex[b.index + "," + a.index] || a.index == b.index;
   }

       function fade(opacity) {
       return function(d) {
           node.style("stroke-opacity", function(o) {
                       thisOpacity = isConnected(d, o) ? 1 : opacity;
                       this.setAttribute('fill-opacity', thisOpacity);
               return thisOpacity;
                       });

                       link.style("stroke-opacity", opacity).style("stroke-opacity",
function(o) {
               return o.source === d || o.target === d ? 1 : opacity;
               });
       };
       }

});
4

3 に答える 3

61

フォースレイアウトに関する私の講演には、バウンディングボックスの例があります。位置Verlet統合により、「ティック」イベントリスナー内で幾何学的制約(バウンディングボックスや衝突検出など)を定義できます。制約に準拠するようにノードを移動するだけで、シミュレーションはそれに応じて適応します。

とはいえ、重力は、ユーザーがグラフをバウンディングボックスの外に一時的にドラッグして、グラフが回復するため、この問題に対処するためのより柔軟な方法です。グラフのサイズと表示される領域のサイズに応じて、グラフを適合させるために、重力と電荷(反発)の相対的な強さを変えて実験する必要があります。

于 2012-03-06T02:45:25.080 に答える
1

コメント付きのコードは、定義から、svg g(rouping) 要素であり、cx/cy 属性を操作しないノードで機能します。ノード内の circle 要素を選択して、これらの属性を有効にします。

node.select("circle") // select the circle element in that node
    .attr("cx", function(d) { return d.x = Math.max(r, Math.min(w - r, d.x)); })
    .attr("cy", function(d) { return d.y = Math.max(r, Math.min(h - r, d.y)); });
于 2016-10-25T02:15:02.863 に答える