2012-05-01 37 views
56

Tôi muốn một số nút trong bố cục theo hướng lực lượng của tôi bỏ qua lực và ở vị trí cố định dựa trên thuộc tính của nút, trong khi vẫn có thể được kéo và sử dụng đẩy lùi các nút khác và duy trì đường liên kết của chúng. Tôi nghĩ rằng nó sẽ là đơn giản như này:Sửa vị trí nút trong Bố cục có hướng 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 + ")" 
      }); 
    }); 

Tôi cũng đã cố gắng tự đặt x của nút và các thuộc tính y on-ve, nhưng sau đó các liên kết tiếp tục nổi lên đến nơi nút sẽ là nếu nó bị ảnh hưởng bởi lực lượng. Rõ ràng tôi có một sự hiểu lầm cơ bản về cách làm việc này, vì vậy ai đó có thể chỉ cho tôi một ví dụ mà một số nút được cố định ở vị trí của chúng (nhưng vẫn có thể kéo được) và phần còn lại của các nút đang trôi nổi xung quanh lực- giống như hướng dẫn và tất cả các liên kết vẫn hoạt động?

Trả lời

69

Đặt d.fixed trên các nút mong muốn thành đúng và khởi tạo d.xd.y đến vị trí mong muốn. Các nút này sau đó sẽ vẫn là một phần của mô phỏng và bạn có thể sử dụng mã hiển thị thông thường (ví dụ: thiết lập thuộc tính biến đổi); tuy nhiên, vì chúng được đánh dấu là cố định, chúng chỉ có thể được di chuyển bằng cách kéo và không phải bởi mô phỏng.

Xem tài liệu force layout để biết thêm chi tiết và cũng xem cách nút gốc được định vị trong this example.

8

nút d3v4 cố định trong cách bố trí lực lượng

Trong d3v3 d.fixed sẽ sửa chữa các nút ở d.xd.y; tuy nhiên, trong d3v4 phương thức này không còn được hỗ trợ nữa. Các d3v4 documentation trạng thái:

Để khắc phục một nút ở một vị trí nhất định, bạn có thể chỉ định thêm hai tính:

fx - the node’s fixed x-position

fy - the node’s fixed y-position

Vào cuối mỗi đánh dấu, sau khi ứng dụng của bất kỳ lực lượng, một nút với một node.fx được xác định có node.x thiết lập lại giá trị này và node.vx đặt đến 0; tương tự như vậy, một nút với một node.fy đã xác định có node.y đặt lại thành giá trị này và node.vy được đặt thành 0. Để hủy một nút đã được được sửa trước đó, hãy đặt node.fx và node.fy thành null hoặc xóa các thuộc tính này.

Bạn có thể đặt fxfy thuộc tính cho các nút có hiệu lực trong nguồn dữ liệu của bạn, hoặc bạn có thể thêm và loại bỏ fxfy giá trị năng động. Đoạn dưới đây trình bày các đặc tính này ở phần cuối của sự kiện kéo, chỉ cần kéo một nút để sửa chữa vị trí của nó:

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>

Các vấn đề liên quan