更改现有d3树的大小

时间:2015-07-23 13:52:29

标签: javascript d3.js svg tree

我正在尝试创建一个查看Web应用程序的树。我正在使用d3树布局来生成我的树。我希望能够做的是在任一轴上缩放树的大小。在其他方面,能够缩放观看者的x和y轴。这将有效地增加节点之间的垂直距离或增加分支的长度。

我无法做到这一点。我试图更改树布局的nodeSize(),然后更新哪些没有效果。我还尝试修改每个节点的x或y坐标,这些坐标再次没有效果。一旦渲染完毕,我就完全无法修改树的物理布局。

我已阅读并尝试了以下主题中的修复:

但他们没有解决我的问题。

我正在使用原型函数实现一个TreeGenerator对象,该对象处理SVG的所有渲染。我想要一个全屏的感觉,所以TreeGenerator将一个SVG附加到一个width: 100%; height: 100%的div。我应该节点我已经实现了缩放和平移功能。

这是构造函数:     

TreeGenerator = function(target, treeString) {

    // Set up everything here
    // colors
    this.nodeColor = "#3B6073";
    this.highlightColor = "#F22248";
    this.searchColor = "#0DFFC2";

    this.nodeHeight = 5;
    this.nodeLength = 20;

    this.zoomX = 1;
    this.zoomY = 5;

    this._winHeight = window.innerHeight;
    this._winWidth = window.innerWidth;

    //this.xScale = d3.scale.linear().domain([0,100]).range([0, this._winWidth])
    //this.yScale = d3.scale.linear().domain([0,100]).range([0, this._winHeight])

    // keep the matching results from last search
    this._searchResults = [];

    // path lengths
    this.maxPathLength = 0;
    this._loadSVG(target);
    this._tree(treeString);
}

以下是从构造函数调用的两个函数_loadSVG和_tree:     

TreeGenerator.prototype._loadSVG = function(target) {

    var zoom = d3.behavior.zoom()
        //.size([this._winWidth, this._winHeight])
       .scaleExtent([this.zoomX,this.zoomY])
        //.x(this.xScale)
        //.y(this.yScale)
        //.center([height/2, width/2])
        .on("zoom", zoomed);


    var drag = d3.behavior.drag()
        .origin(function(d) { return d; })
        .on("dragstart", dragstarted)
        .on("drag", dragged)
        .on("dragend", dragended);

    this.svg = d3.select(target, ":first-child").append("svg")
      .append("g")
        //.attr("transform", "translate("+width / 2+","+height / 2+")")
        .call(zoom)
        .on("dblclick.zoom", null)

    var rect = this.svg.append("rect")
        .attr("width", "100%")
        .attr("height", "100%")
        .style("fill", "none")
        .style("pointer-events", "all");

    this.container = this.svg.append("g")

    // scope it for d3 funcs
    var container = this.container
    var self = this;

    function dottype(d) {
      d.x = +d.x;
      d.y = +d.y;
      return d;
    }

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

    function dragstarted(d) {
        d3.event.sourceEvent.stopPropagation();
        d3.select(this).classed("dragging", true);
    }

    function dragged(d) {
        d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
    }

    function dragended(d) {
        d3.select(this).classed("dragging", false);
    }
}

并且_tree:

TreeGenerator.prototype._tree = function (treeString) {

    // needs an array for d3
    this.treeData = this.parseTree(treeString);

    this.root = this.treeData[0];

    // set up the layout
    this.tree = d3.layout.tree()
        .nodeSize([this.nodeHeight,this.nodeLength]);

    // set path dists
    this._setPathDist();
    this.yScale = d3.scale.linear().domain([0, this.maxPathLength]).range([0, 20]);
    this.xScale = d3.scale.linear().domain([1,100]).range([10, 30]);

    var self = this;
    update(this.root);

    function update(source) {
        var i = 0;

        // generator for paths from
        // node ---> node
        var horizontal = d3.svg.line().interpolate('step-before')
            .x(function (d) { return d.x; })
            .y(function (d) { return d.y; });

        // Compute the new tree layout.
        var nodes = self.tree.nodes(source).reverse()

        nodes.forEach(function (d) {
            if(!d.pathLength == 0) {
                d.y = d.y * self.yScale(d.pathLength);
            }
            else if(d.children != undefined) {
                d.y += 5;
            }
        });

        links = self.tree.links(nodes);

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

        // Enter the nodes.
        doubleclickTimer = false // dont ask

        var nodeEnter = node.enter().append("g")
            .attr("class", "node")
            .attr("id", function(d) { return "node-"+d.id.toString(); })
            .attr("transform", function(d) { 
                return "translate(" + d.y + "," + d.x + ")"; })
            .on("click", clicked);

        nodeEnter.append("circle")
            .attr("r", 1)
            .style("fill", self.nodeColor)

        nodeEnter.append("text")
            .attr("x", function(d) { 
                return d.children || d._children ? -1 : 1; })
            .attr("y", function(d) {
                return d.children == undefined ? 1 : -1;
            })
            .attr("text-anchor", function(d) { 
                return d.children || d._children ? "end" : "start"; })
            .text(function(d) { return d.name; })
            .style("fill-opacity", 1);

        // try and update
        //var nodeUpdate = node.update()
        //  .attr("x", function(d) { return d.x });

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

        // Enter the links.
        link.enter().insert("path", "g")
            .attr("class", "link")
            .attr("d", function(d) {
                return horizontal([
                    {y: d.source.x, x: d.source.y},
                    {y: d.target.x, x: d.target.y}
                ]);
            });

        function clicked(d) {

            // need the g group for highlight
            node = this;

            // if double click timer is active, this click is the double click
            if ( doubleclickTimer )
            {
                clearTimeout(doubleclickTimer);
                doubleclickTimer = false;
                collapse(d);
            }

            // otherwise, what to do after single click (double click has timed out)
            else {
                doubleclickTimer = setTimeout( function() {
                    doubleclickTimer = false;
                    highlight(node, d);
                }, 175);
            }
        }

        function highlight(node,d) {

            // we want to bold the text
            // and color the node
            self._unhighlightNode();

            // toggle if clicking again
            if(self._highlightedNode == node) {
                self._highlightedNode = undefined;
                self.selectedNode = undefined;
                return;
            }

            // set the new one
            var circle = d3.select(node).select("circle");
            var text = d3.select(node).select("text");

            circle.style("fill", self.highlightColor);
            text.style("font-size","4px");

            // update the pointer
            self._highlightedNode = node;
            self.selectedNode = d;
        }

        function collapse(d) {

        }
    }
};

我知道代码有点混乱,但它只是在我试图解决这个问题时所做的注释。我感谢任何可以提供的帮助。希望我包含足够的信息。

0 个答案:

没有答案