简体   繁体   中英

Append links to side of rectangles in D3 tree layout

I am trying to change each path so that they start from the right side of each rectangle and connect to the left side. Currently they seem to travel "through" the rectangles and have a start/end point somewhere inside the rectangle, not compensating for the size of the rect .

I have tried manipulating this code:

        var diagonal = d3.svg.diagonal()
        .source(function (d) { return { "x": d.source.y, "y": d.source.x }; })
        .target(function (d) { return { "x": d.target.y - 10, "y": d.target.x }; })
        .projection(function (d) { return [d.y + 0, d.x + 0];
      });

but that just ends in disaster but I believe the answer lies somewhere over there.

Here is a JSFiddle of the script as it stands http://jsfiddle.net/ra26wnbb/ .

UPDATE I have viewed D3 tree square node not in desired position but I am not sure it will work with my text wrapping.

First, after the work inside wrap() is done, you need to store the resulting height on the datum of the text: d.height = 19 * (lineNumber + 1); . That way, the height becomes available to whatever needs it. For example, you can use that to set the rect height from outside of wrap() instead of the parentNode.children[0] thing, which is better separation of concerns. Anyway, this is what wrap() ends up being:

    function wrap(text, width) {
        text.each(function (d) { // DIFF add param d
            var text = d3.select(this),
              // DIFF: use datum to get name, instead of element text
              words = d.name.split(/\s+/).reverse(), 
              word,
              line = [],
              lineNumber = 0,
              lineHeight = 1.1, // ems
              y = text.attr("y"),
              dy = parseFloat(text.attr("dy")),
              tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
            while (word = words.pop()) {
                line.push(word);
                tspan.text(line.join(" "));
                if (tspan.node().getComputedTextLength() > width) {
                    line.pop();
                    tspan.text(line.join(" "));
                    line = [word];
                    tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
                }
            }

            // DIFF: store the height via the datum, d
            d.height = 19 * (lineNumber + 1);
            d3.select(this.parentNode.children[0]).attr('height', 19 * (lineNumber + 1));

        });
    }
});

Now that you have d.height you can use it to calculate the necessary offsets of the diagonal's endpoints.

    // calculate source and target offsets
    // d.height gets set by the wrap() function
    var diagonal = d3.svg.diagonal()
        .source(function (d) {
            return {
                "x": d.source.x + d.source.height / 2,
                "y": d.source.y + 150
            };
        })
        .target(function (d) {
            return {
                "x": d.target.x + d.target.height / 2,
                "y": d.target.y
            };
        })
        .projection(function (d) { return [d.y + 0, d.x + 0];
      });

See modified fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM