2014-11-25 15 views
8

Tôi muốn buộc một nhánh sơ đồ sankey lên trên đỉnh.Làm thế nào để ép buộc vị trí y của một nhánh trong plugin d3 sankey?

Thay vì sơ đồ như thế này: Current diagram

muốn tạo sơ đồ nơi các nút 1, 2, 7, 15, 10 và 14 luôn trên đầu trang: Modified diagram

Liên kết để fiddle với hiện tại mã: http://jsfiddle.net/w5jfp9t0/1/

var margin = {top: 1, right: 1, bottom: 6, left: 1}; 
var width = 1052 - margin.left - margin.right; 
var height = 500 - margin.top - margin.bottom; 

var formatNumber = d3.format(",.0f"), 
    format = function(d) { return formatNumber(d); }, 
    color = d3.scale.category20(); 

var svg = d3.select("#chart_sankey").append("svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

var sankey = d3.sankey() 
         .nodeWidth(35) 
         .nodePadding(10) 
         .size([width, height]); 

var path = sankey.link(); 

raw = '{"nodes":[{"name":"Node 1"},{"name":"Node 2"},{"name":"Node 3"},{"name":"Node 4"},{"name":"Node 5"},{"name":"Node 6"},{"name":"Node 7"},{"name":"Node 8"},{"name":"Node 9"},{"name":"Node 10"},{"name":"Node 11"},{"name":"Node 12"},{"name":"Node 13"},{"name":"Node 14"},{"name":"Node 15"}],"links":[{"source":9,"target":13,"value":25},{"source":14,"target":9,"value":37},{"source":14,"target":11,"value":16},{"source":14,"target":12,"value":8},{"source":14,"target":10,"value":68},{"source":6,"target":14,"value":154},{"source":6,"target":8,"value":40},{"source":1,"target":6,"value":345},{"source":1,"target":7,"value":66},{"source":1,"target":3,"value":17},{"source":1,"target":4,"value":25},{"source":1,"target":5,"value":117},{"source":0,"target":1,"value":692},{"source":0,"target":2,"value":19}]}'; 
data = JSON.parse(raw); 

sankey.nodes(data.nodes) 
    .links(data.links) 
    .layout(32); 

var link = svg.append("g") 
      .selectAll(".link") 
      .data(data.links) 
      .enter().append("path") 
      .attr("class", "link") 
      .attr("d", path) 
      .style("stroke-width", function(d) { return Math.max(1, d.dy); }) 
      .sort(function(a, b) { return b.dy - a.dy; }); 

var nodes = data.nodes; 

var node = svg.append("g").selectAll(".node") 
    .data(nodes) 
    .enter().append("g") 
    .attr("class", "node") 
    .attr("transform", function(d) { 
     return "translate(" + d.x + "," + d.y + ")"; }) 
    .call(d3.behavior.drag() 
    .origin(function(d) { return d; }) 
    .on("dragstart", function() { this.parentNode.appendChild(this); }) 
    .on("drag", dragmove)); 

sankey.relayout(); 

node.filter(function(d) { return d.value != 0; }) // append text only if node value is not zero 
    .append("rect") 
    .attr("height", function(d) { return d.dy; }) 
    .attr("width", sankey.nodeWidth()) 
    .style("fill", function(d) { return d.color = color(d.name.replace(/ .*/, "")); }) 
    .style("stroke", function(d) { return d3.rgb(d.color).darker(2); }) 
    .append("title") 
    .text(function(d) { return d.name + "\n" + format(d.value); }); 

node.filter(function(d) { return d.value != 0; }) // append text only if node value is not zero 
    .append("text") 
    .attr("x", -6) 
    .attr("y", function(d) { return d.dy/2; }) 
    .attr("dy", ".35em") 
    .attr("text-anchor", "end") 
    .attr("transform", null) 
    .text(function(d) { return d.name; }) 
    .filter(function(d) { return d.x == 0; }) // at first column append text after column 
    .attr("x", 6 + sankey.nodeWidth()) 
    .attr("text-anchor", "start"); 

function dragmove(d) { 
    d3.select(this).attr("transform", "translate(" + d.x + "," + (d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))) + ")"); 
    sankey.relayout(); 
    link.attr("d", path); 
} 

Tôi cần phải thay đổi gì để thực hiện việc này?

Trả lời

10

Lưu ý Thành thật mà nói, tôi chưa bao giờ sử dụng plugin đó. Tôi không thấy một tùy chọn để có được hành vi mong muốn một cách trực tiếp - vì vậy tôi đã xem xét nguồn của sankey.js để thực hiện các điều chỉnh. Dưới đây tôi thấy làm thế nào tôi muốn thay đổi - bạn có thể muốn làm điều đó kỹ hơn :)

Idea

Nhìn vào mã của sankey.js, bạn thấy rằng các nút được đặt (y-hướng) bằng cách sử dụng chức năng center:

function center(node) { 
    return node.y + node.dy/2; 
} 

Như tôi đã không nhìn thấy một tham số để thay đổi hành vi đó, bạn có thể thay đổi nó để:

function center(node) { 
    return 0; 
} 

Nếu bạn sau đó cũng trở lại thứ tự sắp xếp:

function ascendingDepth(a, b) { 
    return b.y - a.y; 
} 

bạn có được hình ảnh sau đây:

enter image description here

+0

Nó hoạt động như một nét duyên dáng! Cảm ơn bạn! Tôi hy vọng tôi sẽ tìm ra cách di chuyển nút 14 lên trên cùng :). – tomazzlender

+2

Đừng quá nhanh để chấp nhận :) có thể những người khác có cách tiếp cận khác nhau. Ngoài ra, bạn có thể muốn chơi với chức năng sắp xếp (có thể dựa trên một số thuộc tính khác) để có được các hiệu ứng khác. Chúc may mắn! (Tôi kinda giữ câu trả lời của tôi "mở kết thúc" cố tình :)) –

+0

Giải pháp của bạn là đủ tốt cho thời điểm này, nhưng bạn có quyền rằng những người khác có thể đóng góp các giải pháp khác nhau. :) – tomazzlender

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