首页 > 解决方案 > d3 垂直树 - 为路径添加标签

问题描述

我正在制作基于http://bl.ocks.org/d3noob/8326869的 d3 v4 垂直树图,并且我正在尝试向路径添加文本标签(例如,是、否等)。这是我到目前为止的链接部分中的代码:

function update (source) {
    // Assigns the x and y position for the nodes
    var treeData = treemap(root);

    // Compute the new tree layout.
    var nodes = treeData.descendants(),
        links = treeData.descendants().slice(1);

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

    // ****************** Nodes section ***************************

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

    // Enter any new modes at the parent's previous position.
    var nodeEnter = node.enter().append('g')
    .attr('class', 'node')
    .attr("transform", function (d) {
        return "translate(" + source.x0 + "," + source.y0 + ")";
    })
    .attr("data-info", function (d) { return d.data.info })
    .on('click', click);

    // Add Circle for the nodes
    /*nodeEnter.append('circle')
    .attr('class', 'node')
    .attr("id", function(d){return "node" + d.id;})//id of the node.
    .attr('r', 1e-6)
    .style("fill", function (d) {
        return d._children ? "lightsteelblue" : "#fff";
    });*/
    nodeEnter.append('rect')
    .attr('class', 'node')
    .attr('width', 170)
    .attr('height', 55)
    .attr('x', -85)
    .attr('y', -22)
    .attr('rx',7) //rounding
    .attr('ry',7)
    .attr("id", function(d){return "node" + d.id;});//id of the node.

    nodeEnter.append('text')
    //.attr("dy", ".25em")
    //.attr('x', -23)
    .attr('class', 'node-text')
    .attr("text-anchor", "middle")
    .text(function (d) {
        return d.data.name;
    })
    .call(wrap, 165);

    // UPDATE
    var nodeUpdate = nodeEnter.merge(node);

    // Transition to the proper position for the node
    nodeUpdate.transition()
    .duration(duration)
    .attr("transform", function (d) {
        return "translate(" + d.x + "," + d.y + ")";
    });

    // Update the node attributes and style
    nodeUpdate.select('rect.node')
    .style("fill", function (d) {
        if (d._children) {
            return "#007bff"; // dark blue
        }
    })
    .attr('cursor', 'pointer');

    // Remove any exiting nodes
    var nodeExit = node.exit().transition()
    .duration(duration)
    .attr("transform", function (d) {
        return "translate(" + source.x + "," + source.y + ")";
    })
    .remove();

    // On exit reduce the node circles size to 0
    nodeExit.select('circle')
    .attr('r', 1e-6);

    // On exit reduce the opacity of text labels
    nodeExit.select('text')
    .style('fill-opacity', 1e-6);

    // ****************** links section ***************************

    // Update the links...
    var link = svg.selectAll('path.link')
    .data(links, function (d) {
        return d.id;
    });

    // Enter any new links at the parent's previous position.
    var linkEnter = link.enter().insert('path', 'g')
    .attr("id", function(d){ return ("link" + d.id)})//unique id
    .attr("class", "link")
    .attr('d', function (d) {
        var o = {x: source.x0, y: source.y0}
        return diagonal(o, o);
    });

    // UPDATE
    var linkUpdate = linkEnter.merge(link);

    var linkLabel = link.enter().insert("text","g")
    .attr("class", "link2")
    .attr("id", function(d){ return ("link-label" + d.id)})//unique id
    .attr("dx",function(d){ return (d.parent.x + d.x)/2 })
    .attr("dy",function(d){ return (d.parent.y + d.y)/2 })
    .text(function(d) {
        if (d.data.label === "Yes") {
            this.setAttribute("x",-30);
        } else {
            this.setAttribute("x",10);
        }
        return d.data.label;
    });

    linkUpdate.merge(linkLabel);

    // Transition back to the parent element position
    linkUpdate.transition()
    .duration(duration)
    .attr('d', function (d) {
        svg.select("#link-label" + d.id).transition().duration(duration).attr("dx",function(d){ return (d.parent.x + d.x)/2 })
        .attr("dy",function(d){ return (d.parent.y + d.y)/2});
        return diagonal(d, d.parent)
    });

    // Remove any exiting links
    var linkExit = link.exit().transition()
    .duration(duration)
    .attr('d', function (d) {
        var o = {x: source.x, y: source.y};
        svg.selectAll("#link-label" + d.id).remove();
        return diagonal(o, o)
    })
    .remove();

    // Store the old positions for transition.
    nodes.forEach(function (d) {
        d.x0 = d.x;
        d.y0 = d.y;
    });

“linkEnter.insert("text","g")" 部分是我遇到问题的地方。看起来它一直附加到元素而不是作为兄弟元素,因此它根本不显示,而且我不确定如何对其进行编码以使其不是 的子元素,同时在一个节点被隐藏/显示。

一旦我设法解决了上述问题,我也不确定如何设置坐标,以便文本标签位于路径的中间(或至少靠近它)。

我尝试在节点部分添加类似的代码,但似乎更难找到与路径对齐的正确定位。

======== 编辑:我已经更新了代码,因为它现在似乎可以工作了。我创建了从 JSON 变量中提取数据的 linkLabel。它位于路径旁边,但不与它们重叠。动画并不流畅,但至少它似乎可以工作。

标签: d3.js

解决方案


推荐阅读