2013-02-21 38 views
18

Tôi nhìn mẫu http://bl.ocks.org/mbostock/raw/4063570/:Làm thế nào để sử dụng chức năng đường chéo D3 để vẽ các đường cong?

enter image description here

Nó tạo ra dòng sáp nhập đẹp từ mục tiêu nguồn từ trái sang phải.

Trong trường hợp của tôi, tôi cần phải bố trí các nút theo cách thủ công và đặt tọa độ x, y. Trong trường hợp này, các dòng không được hợp nhất tại các nút nguồn. Đây là mã thử nghiệm mà sinh sản vấn đề này:

var data = [ {name: "p1", children: [{name: "c1"}, {name: "c2"}, {name: "c3"}, {name: "c4"}]}]; 
var width = 400, height = 200, radius = 10, gap = 50; 

// test layout 
var nodes = []; 
var links = []; 
data.forEach(function(d, i) { 
    d.x = width/4; 
    d.y = height/2; 
    nodes.push(d); 
    d.children.forEach(function(c, i) { 
     c.x = 3*width/4; 
     c.y = gap * (i +1) -2*radius; 
     nodes.push(c); 
     links.push({source: d, target: c}); 
    }) 
}) 

var color = d3.scale.category20(); 

var svg = d3.select("#chart").append("svg") 
     .attr("width", width) 
     .attr("height", height) 
     .append("g"); 
var diagonal = d3.svg.diagonal() 
     .projection(function(d) { return [d.x, d.y]; }); 

var link = svg.selectAll(".link") 
     .data(links) 
     .enter().append("path") 
     .attr("class", "link") 
     .attr("d", diagonal); 

var circle = svg.selectAll(".circle") 
     .data(nodes) 
     .enter() 
     .append("g") 
     .attr("class", "circle"); 

var el = circle.append("circle") 
     .attr("cx", function(d) {return d.x}) 
     .attr("cy", function(d) {return d.y}) 
     .attr("r", radius) 
     .style("fill", function(d) {return color(d.name)}) 
     .append("title").text(function(d) {return d.name}); 

Có mẫu này tại http://jsfiddle.net/zmagdum/qsEbd/:

enter image description here

Tuy nhiên, có vẻ như hành vi của đường cong gần nút là trái ngược với mong muốn . Tôi muốn họ bắt đầu thẳng theo chiều ngang tại các nút và tạo một đường cong ở giữa. Có một mẹo để làm điều này?

Trả lời

7

Lưu ý rằng trong ví dụ về khối, giá trị x và y được hoán đổi trong các liên kết. Điều này thường sẽ vẽ các liên kết ở vị trí sai, nhưng anh ta cũng cung cấp một chức năng chiếu để hoán đổi chúng trở lại.

var diagonal = d3.svg.diagonal() 
    .projection(function(d) { return [d.y, d.x]; }); 

Dưới đây là jsfiddle của bạn với kỹ thuật này được áp dụng: http://jsfiddle.net/bmdhacks/qsEbd/5/

+0

Điều cần làm nếu tôi muốn tạo liên kết giữa hai trẻ em? Giống như đứa trẻ đầu tiên được liên kết với đứa con thứ hai trong hàng đầu tiên sau khi root? –

25

giải pháp này được dựa trên giải pháp @bmdhacks tuyệt vời, tuy nhiên, tôi tin rằng tôi là tốt hơn một chút, vì nó không đòi hỏi trao đổi xy trong chính dữ liệu.

Ý tưởng là bạn có thể sử dụng diagonal.source()diagonal.target() để trao đổi xy:

var diagonal = d3.svg.diagonal() 
    .source(function(d) { return {"x":d.source.y, "y":d.source.x}; })    
    .target(function(d) { return {"x":d.target.y, "y":d.target.x}; }) 
    .projection(function(d) { return [d.y, d.x]; }); 

Tất cả x y trao đổi bây giờ được gói gọn trong đoạn mã trên.

Kết quả:

enter image description here

Đây cũng là jsfiddle.

+0

Cảm ơn bạn đã đưa ra ví dụ này cho thấy rằng các giá trị trả về dự kiến ​​cho 'nguồn' và' phép chiếu' là khác nhau. –

+0

Điều gì sẽ xảy ra nếu có nhiều liên kết giữa hai nút? Làm thế nào tôi có thể hiển thị nó mà không bị chồng chéo? – Jerry

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