2013-08-07 3 views
3

웹 시각화에 참여하기 시작한 순간으로 저는 완전히 초보자입니다. 내 목표는 루트 노드가 여러 부모와 자식을 가질 수있는 패밀리 트리를 표시하는 것입니다. 해결책을 찾고있는 동안 나는이 예를 발견했다 : http://bl.ocks.org/jdarling/2503502 그것은 내가 필요한 기능을 가지고있는 것처럼 보이기 때문에 위대하다. 그러나, 나는 방향 (상단 - 하단)을 변경하고 싶습니다. 이 예제를 사용하여 시도 : http://bl.ocks.org/mbostock/3184089하지만 실패했습니다.D3 트리 레이아웃의 방향을 90도까지 변경하는 방법

내 코드 :

var tree = d3.layout.tree() 
    .size([height, width]); 

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

var elbow = function (d, i){ 
    var source = calcTop(d.source); 
    var target = calcTop(d.target); 
    var hx = (target.x-source.x)/2; 
    if(d.isRight) 
     hx = -hx; 
    return "M" + source.x + "," + source.y 
      + "H" + (source.x+hx) 
      + "V" + target.y + "H" + target.x; 
}; 

var connector = elbow; 

var calcTop = function(d){ 
    var top = d.x; 
    if(!d.isRight){ 
     top = d.x-halfHeight; 
     top = halfHeight - top; 
    } 
    return {x : top, y : d.y}; 
}; 

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

d3.json("tree.json", function(json) { 
    root = json; 
    root.x0 = height/2; 
    root.y0 = width/2; 
    var t1 = d3.layout.tree() 
     .size([halfHeight, width]) 
     .children(function(d){ 
      return d.winners; 
     }); 
    var t2 = d3.layout.tree() 
     .size([halfHeight, width]) 
     .children(function(d){ 
      return d.challengers; 
     }); 
    t1.nodes(root); 
    t2.nodes(root); 

    var rebuildChildren = function(node){ 
     node.children = getChildren(node); 
     if(node.children) 
      node.children.forEach(rebuildChildren); 
    } 
    rebuildChildren(root); 
    root.isRight = false; 
    update(root); 
}); 

var toArray = function(item, arr){ 
    arr = arr || []; 
    var i = 0, l = item.children?item.children.length:0; 
    arr.push(item); 
    for(; i < l; i++){ 
     toArray(item.children[i], arr); 
    } 
    return arr; 
}; 

function update(source) { 
// Compute the new tree layout. 
var nodes = toArray(source); 

// Normalize for fixed-depth. 
nodes.forEach(function(d) { d.x = d.depth * 180 + halfHeight; }); 

// Update the nodes… 
var node = vis.selectAll("g.node") 
    .data(nodes, function(d) { return d.id || (d.id = ++i); }); 

// Enter any new nodes at the parent's previous position. 
var nodeEnter = node.enter().append("g") 
    .attr("class", "node") 
    .attr("transform", function(d) { 
     return "translate(" + source.x0 + "," + source.y0 + ")"; 
    }) 
    .on("click", click); 

nodeEnter.append("circle") 
    .attr("r", 1e-6) 
    .style("fill", function(d) { 
     return d._children ? "lightsteelblue" : "#fff"; 
    }); 

nodeEnter.append("text") 
    .attr("dy", function(d) { return d.isRight?14:-8;}) 
    .attr("text-anchor", "middle") 
    .text(function(d) { return d.name; }) 
    .style("fill-opacity", 1e-6); 

// Transition nodes to their new position. 
var nodeUpdate = node.transition() 
    .duration(duration) 
    .attr("transform", function(d) { 
     p = calcTop(d); 
     return "translate(" + p.x + "," + p.y + ")"; 
}); 

nodeUpdate.select("circle") 
    .attr("r", 4.5) 
    .style("fill", function(d) { 
     return d._children ? "lightsteelblue" : "#fff"; 
    }); 

nodeUpdate.select("text") 
    .style("fill-opacity", 1); 

// Transition exiting nodes to the parent's new position. 
var nodeExit = node.exit().transition() 
    .duration(duration) 
    .attr("transform", function(d) { 
     p = calcTop(d.parent||source); 
     return "translate(" + p.x + "," + p.y + ")"; 
    }) 
    .remove(); 

nodeExit.select("circle") 
    .attr("r", 1e-6); 

nodeExit.select("text") 
    .style("fill-opacity", 1e-6); 

// Update the links... 
var link = vis.selectAll("path.link") 
    .data(tree.links(nodes), function(d) { return d.target.id; }); 

// Enter any new links at the parent's previous position. 
link.enter().insert("path", "g") 
    .attr("class", "link") 
    .attr("d", function(d) { 
     var o = {x: source.x0, y: source.y0}; 
     return connector({source: o, target: o}); 
    }); 

// Transition links to their new position. 
link.transition() 
    .duration(duration) 
    .attr("d", connector); 

// Transition exiting nodes to the parent's new position. 
link.exit() 
    .transition() 
    .duration(duration) 
    .attr("d", function(d) { 
     var o = calcTop(d.source||source); 
     if(d.source.isRight) 
      o.x -= halfHeight - (d.target.x - d.source.x); 
     else 
      o.x += halfHeight - (d.target.x - d.source.x); 
     return connector({source: o, target: o}); 
    }) 
    .remove(); 

// Stash the old positions for transition. 
nodes.forEach(function(d) { 
    var p = calcTop(d); 
    d.x0 = p.x; 
    d.y0 = p.y; 
}); 

// Toggle children on click. 
function click(d) { 
    if (d.children) { 
     d._children = d.children; 
     d.children = null; 
    } else { 
     d.children = d._children; 
     d._children = null; 
    } 
update(source); 

} 은}

정말 도움을 주셔서 감사합니다겠습니까!

+0

일반적으로 방향은 너비의 높이를 바꿔서 변경됩니다. 우리에게 몇 가지 코드를 보여 주면 잘못된 위치를 알 수 있습니다. –

+0

감사합니다. 예, 시도하고 있지만 여전히 올바르게 작동하지 않습니다. 코드로 내 질문을 업데이트했습니다. –

+0

더 복잡한 작업을 시도하기 전에 다음을 변경할 수 있습니까? .attr ("transform", function (d) {return "translate ("+ source.x0 + ","+ source.y0 + ")";})) to. –

답변

4

보고있는 예제가 실제로 뒤집 혔습니다. 이로 인해 혼란 스러울 수 있습니다. D3의 트리는 자연스럽게 하향식 트리이며 코드는 트리를 옆으로 향하게하기 위해 많은 x-y를 뒤집습니다.

var nodeUpdate = node.transition() 
     .duration(duration) 
     .attr("transform", function(d) { p = calcLeft(d); return "translate(" + p.y + "," + p.x + ")"; }) 
     ; 

var nodeUpdate = node.transition() 
     .duration(duration) 
     .attr("transform", function(d) { p = calcLeft(d); return "translate(" + p.x + "," + p.y + ")"; }) 
     ; 

에 변경하면 올바른 위치에 표시하는 노드를 얻을 것이다. update() 내의 x-y 좌표를 바꿔서 비슷한 변화를 주면 대부분의 위치 지정 문제가 해결됩니다. 마지막 한가지는

return "M" + source.y + "," + source.x 
     + "H" + (source.y+hy) 
     + "V" + target.x + "H" + target.y; 

이 수직 수평 수직 수평 수직 수평에서 커넥터의 모양을 변경

return "M" + source.x + "," + source.y 
     + "V" + (source.y+hy) 
     + "H" + target.x + "V" + target.y; 

로 변경해야합니다 당신이 전화를 원하는 팔꿈치 기능/변수 /입니다. 이것은 d3이 아닌 원시 SVG 라인입니다. 내가 만든 변경 사항 (너비와 높이 교환, AJAX JSON 요청 변경으로 데이터 하드 코딩 - AJAX는 바이올린에서 작동하기가 어렵습니다)은 모두 http://jsfiddle.net/Zj3th/2/입니다.

d3 및 SVG에 대한 경험이 없다면 코드를 수정하기 전에 http://blog.pixelingene.com/2011/07/building-a-tree-diagram-in-d3-js/과 같은 간단한 예제를 완전히 이해하고 완전히 이해할 것입니다.

+0

도움을 주셔서 감사합니다. 그것은 내가 필요한 것입니다. –

+0

@ user2668579 - 아주 명확한 용어로 설명하면 ... – VividD

0
its very easy to make rotation in d3 collapsible tree TOP-DOWN.. 

step 1: specify top,bottom,left,right part of our drawing pan and also the width and        
     height. 
Step 2: Make the orientation as top to bottom 
step 3: Reading the json and make the orientation 
step 4: Appending the link and circle to the body 

<script> 
var jdata='${data}' 
    var margin = {top: 20, right: 120, bottom: 20, left: 120}, 
    width = 980 - margin.left - margin.right, 
    height = 500 - margin.top - margin.bottom; 

    var orientations = { 
     "top-to-bottom": { 
     size: [width, height], 
     x: function(d) { return d.x; }, 
     y: function(d) { return d.y; } 
     } 
    }; 

    var svg = d3.select("body").selectAll("svg") 
     .data(d3.entries(orientations)) 
     .enter().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 + ")"); 

    d3.json("resources/grap.json", function(json) { 
     root = JSON.parse(jdata); 

     svg.each(function(orientation) { 
     var svg = d3.select(this), 
      o = orientation.value; 

     // Compute the layout. 
     var tree = d3.layout.tree().size(o.size), 
      nodes = tree.nodes(root), 
      links = tree.links(nodes); 

     // Create the link lines. 
     svg.selectAll(".link") 
      .data(links) 
      .enter().append("path") 
      .attr("class", "link") 
      .attr("d", d3.svg.diagonal().projection(function(d) { return [o.x(d), o.y(d)]; })); 

     // Create the node circles. 
     svg.selectAll(".node") 
      .data(nodes) 
     .enter().append("circle") 
      .attr("r",1.5) 
      .attr("x", o.x) 
      .attr("y", o.y) 

     }); 
    }); 

</script> 
3

다음은 내가 작성한 아래쪽 상단 다이어그램의 예입니다. 어쩌면 당신이 codepen에 등 코드

enter image description here

링크를 몇 가지 아이디어를 발견 것, 그것은 당신을 위해 유용 할 수 있습니다 수집합니다. 언제든지 질문하십시오.

+0

VividB, 조상 트리를 만들기 위해 코드 펫을 사용하고 있습니다. 어떻게 클릭 할 수 있고 접을 수 있습니까? 나는 당신이해야 할 질문을 열 수 있습니다. – diehell

관련 문제