2017-12-13 3 views
2

누군가가 줌 기능이 노드 위에 있고 SVG가 아닌 경우 트리거하는 이유를 아십니까? 나는 줌 기능이 마우스가 svg를 넘어 노드 위에있을 때만 움직이기를 원한다. 누군가가 나를 도울 수 있으면 아주 좋을 것입니다. 어쩌면 그래프에 팬을 추가하는 방법을 아는 사람이 있을까요? 그래프를 팬하려면 우선 순위가 가장 높지 않습니다. 그래프를 확대하는 것이 더 중요합니다. JS Fiddled3 트리 그래프 확대/축소는 노드에만 있습니다

$(document).ready(function() { 
// DATA is a JSON objekt --> see in fiddle 
    let data = DATA     
    var margin = { 
     top: 20, 
     right: 120, 
     bottom: 20, 
     left: 120 
    }, 
    width = 960 - margin.right - margin.left, 
    height = 500 - margin.top - margin.bottom; 

    var i = 0, 
    duration = 750, 
    root; 

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

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

    var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom); 

    function zoom() { 
    console.log('===================================='); 
    console.log("zoom is only on node?"); 
    console.log('===================================='); 
    } 

    var svg = d3.select("#tree-svg") 
    .attr("width", width + margin.right + margin.left) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")") 
    .call(zoomListener) 
    draw(data) 
    function draw(data) { 
    //if (error) throw error; 
    let flare = data 
    root = flare; 
    root.x0 = height/2; 
    root.y0 = 0; 

    function collapse(d) { 
     if (d.children) { 
     d._children = d.children; 
     d._children.forEach(collapse); 
     d.children = null; 
     } 
    } 

    root.children.forEach(collapse); 
    update(root); 
    } 

    d3.select(self.frameElement).style("height", "800px"); 
    function update(source) { 
    // Compute the new tree layout. 
    var nodes = tree.nodes(root).reverse(), 
     links = tree.links(nodes); 

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

    // Update the nodes… 
    var node = svg.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.y0 + "," + source.x0 + ")"; 
     }) 
     .on("click", click); 


    nodeEnter.append("circle") 
     .attr("r", 1e-6) 
     .style("fill", function(d) { 
     return d._children ? "lightsteelblue" : "#fff"; 
     }); 
    nodeEnter.append("text") 
     .attr("x", function(d) { 
     return d.children || d._children ? -10 : 10; 
     }) 
     .attr("dy", ".35em") 
     .attr("text-anchor", function(d) { 
     return d.children || d._children ? "end" : "start"; 
     }) 
     .text(function(d) { 
     return d.name; 
     }) 
     .style("fill", "black"); 

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

    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) { 
     return "translate(" + source.y + "," + source.x + ")"; 
     }) 
     .remove(); 

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

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

    // Update the links… 
    var link = svg.selectAll("path.link") 
     .data(links, 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 diagonal({ 
      source: o, 
      target: o 
     }); 
     }); 

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

    // Transition exiting nodes to the parent's new position. 
    link.exit().transition() 
     .duration(duration) 
     .attr("d", function(d) { 
     var o = { 
      x: source.x, 
      y: source.y 
     }; 
     return diagonal({ 
      source: o, 
      target: o 
     }); 
     }) 
     .remove(); 

    // Stash the old positions for transition. 
    nodes.forEach(function(d) { 
     d.x0 = d.x; 
     d.y0 = d.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(d); 
    } 
}) 

답변

1

당신은 줌 리스너에 따라 행동 할 수있는 모든 노드를 보유 그룹을 추가해야합니다.

var svgGroup = baseSvg.append("g"); 

var baseSvg = d3.select("#tree-container").append("svg") 
    .attr("width", viewerWidth) 
    .attr("height", viewerHeight) 
    .attr("class", "overlay") 
    .call(zoomListener); 

function zoom() { 
    svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); 
} 

이 예제는 http://bl.ocks.org/robschmuecker/7880033을 참조하십시오. 팬도 거기에 표시됩니다.

+0

robschmuecker의 예가 다소 버그가 있습니다. 때로는 원이 사라집니다. ....하지만 고마워요 :) –

+0

그리고 나는 코드를 이해하지 못합니다. (어쩌면 누군가 다른 해결책을 가지고 있습니까? –

+0

내 코드에 zoomListener도 있습니다. 그러나 여전히 작동하지 않습니다. –