2012-05-01 15 views
56

force-directedレイアウトのノードのいくつかが強制を無視し、ノードの属性に基づいて固定位置にとどまり、引き続きドラッグ&他のノードで反発し、リンク線を維持する。私はそれがこのような単純なものだろうと思った:D3のForce-Directedレイアウトのノード位置を固定する

force.on("tick", function() { 
     vis.selectAll("g.node") 
      .attr("transform", function(d) { 
       return (d.someAttribute == true) ? 
        "translate(" + d.xcoordFromAttribute + "," + d.ycoordFromAttribute +")" : 
        "translate(" + d.x + "," + d.y + ")" 
      }); 
    }); 

私も手動で-TICKノードのxとy属性を設定しようとしたが、その後のリンクがあれば、ノードは次のようになりどこに出てフロートし続けますその力によって影響を受けた。

明らかに、私はこれがどのように動作するのかという基本的な誤解を抱いています。したがって、ノードの位置が固定されていても(しかし、まだドラッグ可能です)、残りのノードは、指向のような、すべてのリンクはまだ動作していますか?

答えて

69

希望するノードのd.fixedをtrueに設定し、d.xd.yを目的の位置に初期化します。これらのノードは引き続きシミュレーションの一部となり、通常の表示コード(たとえば、変換属性の設定)を使用できます。ただし、固定されているとマークされているため、シミュレーションではなくドラッグするだけで移動できます。

詳細については、force layoutのドキュメントを参照してください。また、ルートノードの配置方法はthis exampleです。力レイアウトの

8

d3v4固定ノードd.xd.yのノードを修正するd3v3 d.fixed

。ただし、d3v4ではこのメソッドはサポートされなくなりました。 d3v4 documentation状態:後、各目盛りの終わりに

fx - the node’s fixed x-position

fy - the node’s fixed y-position

与えられた位置にノードを修正するには、次の2つの追加 のプロパティを指定することもできます任意の力の適用、ノード と定義されたnode.fxはnode.xをこの値にリセットし、node.vxは をゼロに設定します。同様に、定義されたnode.fyを持つノードは、node.yを にリセットし、この値とnode.vyをゼロに設定します。 が以前に修正されたノードの固定を解除するには、node.fxとnode.fyをnullに設定するか、これらの属性を削除してください( )。

あなたのデータソースの力ノードにfxfy属性を設定することもできますし、動的にfxfy値を追加および削除することができます。以下のスニペットは、ちょうどその位置を固定するためのノードをドラッグし、ドラッグイベントの終了時にこれらのプロパティを設定:

var data ={ 
 
"nodes": 
 
    [{"id": "A"},{"id": "B"},{"id": "C"},{"id":"D"}], 
 
"links": 
 
    [{"source": "A", "target": "B"}, 
 
    {"source": "B", "target": "C"}, 
 
    {"source": "C", "target": "A"}, 
 
    {"source": "D", "target": "A"}] 
 
} 
 
var height = 250; 
 
var width = 400; 
 

 
var svg = d3.select("body").append("svg") 
 
    .attr("width",width) 
 
    .attr("height",height); 
 
    
 
var simulation = d3.forceSimulation() 
 
    .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(50)) 
 
    .force("charge", d3.forceManyBody()) 
 
    .force("center", d3.forceCenter(width/2, height/2)); 
 
    
 
var link = svg.append("g") 
 
    .selectAll("line") 
 
    .data(data.links) 
 
    .enter().append("line") 
 
    .attr("stroke","black"); 
 

 
var node = svg.append("g") 
 
.selectAll("circle") 
 
.data(data.nodes) 
 
.enter().append("circle") 
 
.attr("r", 5) 
 
.call(d3.drag() 
 
    .on("start", dragstarted) 
 
    .on("drag", dragged) 
 
    .on("end", dragended)); 
 
    
 
simulation 
 
.nodes(data.nodes) 
 
.on("tick", ticked); 
 

 
simulation.force("link") 
 
.links(data.links); 
 
     
 
function ticked() { 
 
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; }); 
 
node 
 
    .attr("cx", function(d) { return d.x; }) 
 
    .attr("cy", function(d) { return d.y; }); 
 
}  
 
    
 
function dragstarted(d) { 
 
    d.fx = null; 
 
    d.fy = null; 
 
} 
 

 
function dragged(d) { 
 
    d.x = d3.event.x; 
 
    d.y = d3.event.y; 
 
} 
 

 
function dragended(d) { 
 
    d.fx = d3.event.x; 
 
    d.fy = d3.event.y; 
 
} 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.6.0/d3.min.js"></script>