d3.js tree佈局,節點居中顯示

你是否有着這樣的煩惱,你的樹圖太大,超出部分需要使用滾動條,這時需要快速的找到其中一個節點該怎麼辦?

實現的效果圖如下:

代碼如下:


var nodeX=0,nodeY=0;
d3Tree();

$("#wrapper").animate({scrollTop:nodeY+"px" }, 200);
$("#wrapper").animate({scrollLeft:nodeX+"px" }, 200);

function d3Tree(){
    $("#tree-container svg").remove();
    //$("#tree-container").html('');

    var svgW = 2000,svgH = 2500;
    var margin = {top: 20, right: 120, bottom: 20, left: 120},
	width  = svgW - margin.right - margin.left,
	height = svgH - margin.top   - margin.bottom;

    var i = 0;

    var tree = d3.layout.tree()
        .nodeSize([15, 150]);
    	//.size([height, width]);

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

    var svg = d3.select("#tree-container").append("svg")
    	.attr("width", width + margin.right + margin.left)
    	.attr("height", height + margin.top + margin.bottom)
        .attr("id","treeSvg")
        .append("g")
        .attr("id","g_main")
    	.attr("transform","translate(" + margin.left + "," + svgH/2 + ")");

    var root = treeData;

    update(root);

    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; });

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

        // Enter the nodes.
        var nodeEnter = node.enter().append("g")
            .attr("class", function(d){
                if(d.ac==1){
                    var bw = $("#wrapper").width(); //窗口的寬
                    var bh = $("#wrapper").height(); //窗口的高
                    var ggg = d3.select("#g_main").attr("transform");
                    var gg = ggg.substring(10,ggg.length-1);
                    var g = gg.split(",");
                    var gx = Number(g[0]), gy = Number(g[1]); //g元素的位置,以第一個節點爲原點
                    var x = d.y + gx, y = d.x + gy; //該元素在wrapper左上角的位置

                    nodeX = x-bw/2; //設置的scrollLeft的值
                    nodeY = y-bh/2; //設置的scrollTop的值

                    return "node active"; //特殊標記
                }else{
                    return "node";
                }
            })
            .attr("transform", function(d) {
                return "translate(" + d.y + "," + d.x + ")";
            })
            .on("click", click);

        nodeEnter.append("circle")
        .attr("r", function(d) {
            return d.radius;
        })
        .style("fill", function(d) {
            return d.fillColor;
        })
        .style("stroke", function(d) {
            return d.strokeColor;
        });

        nodeEnter.append("text")
            .attr("x", function(d) {
                return d.children || d._children ? (15) * -1 : + 15
            })
            .attr("dy", ".35em")
            .attr("text-anchor", function(d) {
                return d.children || d._children ? "end" : "start";
            })
            .text(function(d) {
                //console.log(d)
                return d.name;
            })
            .style("fill-opacity", 1);

      // Declare the links…
        var link = svg.selectAll("path.link")
            .data(links, function(d) { return d.target.id; });

        // Enter the links.
        link.enter().insert("path", "g")
            .attr("class", "link")
            .style("stroke", function(d) { return d.target.lineColor; })
            .attr("d", diagonal);
    }
}

看到上面這段代碼是不是有些頭大?哈哈,其實主要的難點在與獲取你選擇人員的節點位置,也就是下面這段這裏:

if(d.ac==1){
    var bw = $("#wrapper").width(); //可視窗口的寬
    var bh = $("#wrapper").height(); //可視窗口的高
    var ggg = d3.select("#g_main").attr("transform"); //獲得g元素的translate(x,y)
    var gg = ggg.substring(10,ggg.length-1); //得到x,y字符串
    var g = gg.split(","); //拆分字符串
    var gx = Number(g[0]), gy = Number(g[1]); //字符串轉數字
    var x = d.y + gx, y = d.x + gy; //得到該元素在wrapper左上角的位置,因爲該元素在wrapper中的位置=g元素的位置+該元素的x,y

    nodeX = x-bw/2; //設置的scrollLeft的值
    nodeY = y-bh/2; //設置的scrollTop的值

    return "node active"; //特殊標記
}else{
    return "node";
}

該方法僅供參考,具體應以實際需求適當調整。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章