2012-05-01 182 views
56

我希望我的力量指揮佈局中的一些節點忽略力量並且保留在基於節點屬性的固定位置,同時仍然能夠被拖拽並施加力量在其他節點上排斥並保持其鏈接線。我認爲這將是如此簡單:固定節點位置在D3力導向佈局

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 + ")" 
      }); 
    }); 

我也嘗試手動設置節點上剔x和y的屬性,但隨後的鏈接繼續浮於其中的節點是,如果它受到部隊的影響。

很顯然,我對這個應該如何工作有一個基本的誤解,所以有人可以指點我一個例子,其中一些節點固定在他們的位置(但仍然可拖動),其餘節點都是圍繞着力 - 直指式,並且所有鏈接仍在工作?

回答

69

將所需節點上的d.fixed設置爲true,並將d.xd.y初始化爲所需位置。這些節點將仍然是模擬的一部分,並且您可以使用正常的顯示代碼(例如,設置transform屬性)。但是,因爲它們被標記爲固定,所以只能通過拖動來移動,而不能通過模擬進行移動。

有關更多詳細信息,請參閱force layout文檔,並瞭解根節點在this example中的位置。在力佈局

8

d3v4固定節點

在D3V3 d.fixed將在d.xd.y固定節點;但是,在d3v4中,不再支持此方法。該d3v4 documentation狀態:

要解決在給定位置的一個節點,你可以指定另外兩個 屬性:

fx - the node’s fixed x-position

fy - the node’s fixed y-position

在每個週期結束,後施加任何力,節點 與定義的節點.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>