在D3中包装长文本标签而无需额外的新行

时间:2016-07-20 17:52:52

标签: javascript d3.js label

利用Mike Bostock’s Wrapping Long Labels function我能够在D3.js中包装长文本标签。但是我发现当我需要将特定文本包装成两行以上时,我的D3图表会插入额外的新行。没有这些额外的新线路,请你帮我装一下吗? enter image description here

这是我的标签数据和Mike Bostock的代码。

treeData = {
    'name': 'Good Short Label',
    'parent': 'null',
    '_children': [
        {'name': 'Very Very Long Good Wapped Label'},
        {'name': 'Very Very Very Very Very Very Very Very Very Long Label With Extra New Line'},
        {'name': 'Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Long Label With Extra New Lines'}
    ]
};

function wrap(text, width) {
    text.each(function () {
        var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            word,
            line = [],
            lineNumber = 0,
            lineHeight = 1.1, // ems
            x = text.attr('x'),
            y = text.attr('y'),
            dy = 0, //parseFloat(text.attr('dy')),
            tspan = text.text(null)
                .append('tspan')
                .attr('x', x)
                .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', x)
                    .attr('y', y)
                    .attr('dy', ++lineNumber * lineHeight + dy + 'em')
                    .text(word);
            }
        }
    });
}

以下是复制此内容的jsfiddle link

1 个答案:

答案 0 :(得分:2)

不要增加lineHeight变量

.attr('dy', ++lineNumber * lineHeight + dy + 'em')  // add a newline multiple times
.attr('dy', lineHeight + dy + 'em') // adds only one new line



var treeData = {
    'name': 'Good Short Label',
    'parent': 'null',
    '_children': [
        {'name': 'Very Very Long Good Wapped Label'},
        {'name': 'Very Very Very Very Very Very Very Very Very Long Label With Extra New Line'},
        {'name': 'Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Very Long Label With Extra New Lines'}
    ]
};

var margin = {top: 20, right: 120, bottom: 20, left: 200};
var width = 950 - margin.right - margin.left;
var height = 800 - margin.top - margin.bottom;

var i = 0;
var duration = 750;
var root;

var tree = d3.layout.tree().size([height, width]);

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

var svg = d3.select('#tree').append('svg')
    .attr('width', width + margin.right + margin.left)
    .attr('height', height + margin.top + margin.bottom)
    .append('g')
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');


root = treeData;
root.x0 = height / 2;
root.y0 = 0;

update(root);
d3.select(self.frameElement).style('height', '800px');


function update(source) {
    // Compute the new tree layout.
    var nodes = tree.nodes(root).reverse();
    var links = tree.links(nodes);

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

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

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

    nodeEnter.append('circle')
        .attr('r', 1e-6)
        .style('fill', function (d) {
            return d._children ? '#ccff99' : '#fff';
        });

    nodeEnter.append('text')
        .attr('x', function (d) {
            return d.children || d._children ? -13 : 13;
        })
        .attr('dy', '.35em')
        .attr('text-anchor', function (d) {
            return d.children || d._children ? 'end' : 'start';
        })
        .text(function (d) {
            return d.name;
        })
        .call(wrap, 150)
        .style('fill-opacitsy', 1e-6)
        .attr('class', function (d) {
            if (d.url != null) {
                return 'hyper';
            }
        })
        .on('click', function (d) {
            $('.hyper').attr('style', 'font-weight:normal');
            d3.select(this).attr('style', 'font-weight:bold');
        })
    ;

    // Transition nodes to their new position.
    var nodeUpdate = node.transition()
        .duration(duration)
        .attr('transform', function (d) {
            return 'translate(' + d.y + ',' + d.x + ')';
        });

    nodeUpdate.select('circle')
        .attr('r', 10)
        .style('fill', function (d) {
            return d._children ? '#ccff99' : '#fff';
        });

    nodeUpdate.select('text')
        .style('fill-opacity', 1);

    // Transition exiting nodes to the parent's new position.
    var nodeExit = node.exit().transition()
        .duration(duration)
        .attr('transform', function (d) {
            return 'translate(' + source.y + ',' + source.x + ')';
        })
        .remove();

    nodeExit.select('circle')
        .attr('r', 1e-6);

    nodeExit.select('text')
        .style('fill-opacity', 1e-6);

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

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

    // Transition links to their new position.
    link.transition()
        .duration(duration)
        .attr('d', diagonal);

    // Transition exiting nodes to the parent's new position.
    link.exit().transition()
        .duration(duration)
        .attr('d', function (d) {
            var o = {x: source.x, y: source.y};
            return diagonal({source: o, target: o});
        })
        .remove();

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

// Toggle children on click.
function click(d) {
    if (d.children) {
        d._children = d.children;
        d.children = null;
    } else {
        d.children = d._children;
        d._children = null;
    }
    update(d);
}


function wrap(text, width) {
    text.each(function () {
        var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            word,
            line = [],
            lineNumber = 0,
            lineHeight = 1.1, // ems
            x = text.attr('x'),
            y = text.attr('y'),
            dy = 0, //parseFloat(text.attr('dy')),
            tspan = text.text(null)
                .append('tspan')
                .attr('x', x)
                .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', x)
                    .attr('y', y)
                    .attr('dy', lineHeight + dy + 'em')
                    .text(word);
            }
        }
    });
}

#vid-container {
    width: 100%;
    height: 100%;
    width: 820px;
    height: 461.25px;
    float: none;
    clear: both;
    margin: 2px auto;
}

svg {
    border-radius: 3px;
}

.node {
    cursor: pointer;
}

.node circle {
    fill: #fff;
    stroke: #99ccff;;
    stroke-width: 3px;
}

.node text {
    font: 12px sans-serif;
}

.link {
    fill: none;
    stroke: #99ccff;
    stroke-width: 2px;
}

.hyper {
    color: red;
    text-decoration: underline;
}

.hyper:hover {
    color: yellow;
    text-decoration: none;
}

.selected {
    font-weight: bold;
}

.not-selected {
    font-weight: normtal;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id='tree'></div>
&#13;
&#13;
&#13;