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

该方法仅供参考,具体应以实际需求适当调整。

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