在选项卡式显示

时间:2017-08-03 14:57:46

标签: twitter-bootstrap d3.js svg tabs

我正在使用从ericsoco借来的函数来将文本换行超出SVG元素中的某个宽度。该网页有一个(Bootstrap)标签界面,可以连接许多SVG元素。文本换行功能在第一个选项卡上完美运行,但在第二个选项卡上不运行。不知何故,tab函数似乎干扰了文本换行功能。

网页位于https://manypossibilities.net/spectrum-chart/index.html 和完整的源代码可以在 https://github.com/stevesong/spectrum-chart/blob/master/index.htmlhttps://github.com/stevesong/spectrum-chart/blob/master/byCountry.js

您可以看到名称为Telecom Namibia的名称在第一个选项卡上正确包装但在第二个选项卡上没有。 Wrapped text works in first tab but not second

自动换行功能如下:

function wrap(text, width) {
    text.each(function() {
        var breakChars = ['/', '&', '-'],
            text = d3.select(this),
            textContent = text.text(),
            spanContent;
        breakChars.forEach(char => {
            // Add a space after each break char for the function to use to determine line breaks
            textContent = textContent.replace(char, char + ' ');
        });
        var words = textContent.split(/\s+/).reverse(),
            word,
            line = [],
            lineNumber = 0,
            lineHeight = 1.1, // ems
            x = text.attr('x'),
            y = text.attr('y'),
            dy = parseFloat(text.attr('dy') || 0),
            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();
                spanContent = line.join(' ');
                breakChars.forEach(char => {
                    // Remove spaces trailing breakChars that were added above
                    spanContent = spanContent.replace(char + ' ', char);
                });
                tspan.text(spanContent);
                line = [word];
                tspan = text.append('tspan').attr('x', x).attr('y', y).attr('dy', ++lineNumber * lineHeight + dy + 'em').text(word);
            }
        }
    });
}

1 个答案:

答案 0 :(得分:1)

更新:我不再按照以下详细说明进行操作;在大型项目上跟踪活跃的divsvg太难了。相反,我使用它:

var plate;
document.addEventListener('DOMContentLoaded', function () {
    plate = d3.select('body').append('svg').style('position', 'absolute')
        .style('left', '-1000px');
});
function getTextWidth (str) {
    var text = plate.append('text').text(str),
        width = text.node().getComputedTextLength();
    text.remove();
    return width;
}

它的工作原理是在浏览器窗口外隐藏的svg上绘制文本,然后将其删除(这是可选的)。注意:任何同步脚本都会暂停DOM加载,因此您应该在创建板svg

时进行冗余

原始答案:

我遇到了类似的问题。当选项卡不是活动选项卡时,Bootstrap会将其隐藏。这意味着使用getComputedTextLength方法将返回0.

解决方案?在所有文本完成绘图后,每个div只要tab-pane 分类,甚至更好:完成所有绘图后。这样,Bootstrap在完成所有计算之前不会隐藏它。

为此,我建议让每个包含div的svg共享一个类,例如holder。然后:

d3.selectAll('div.holder').classed('tab-pane', true);

修改:您还需要删除fade课程才能使用getComputedTextLength

我通过对代码库进行最小程度更改来实现此方法的方法是:

var tabs = d3.selectAll('div.tab-pane').classed('tab-pane', false).classed('fade', false);
//all calls to getComputedTextLength go here
tabs.classed('tab-pane', true).classed('fade', true);

我会使用getComputedTextLength的任何地方。

在您的情况下,我建议您更改:

<script src="https://d3js.org/d3.v4.min.js"></script>
<script type="text/javascript" src="byCountry.js"></script>

对此:

<script src="https://d3js.org/d3.v4.min.js"></script>
<script> var tabs = d3.selectAll('div.tab-pane')
             .classed('tab-pane', false).classed('fade', false);</script>
<script type="text/javascript" src="byCountry.js"></script>
<script> tabs.classed('tab-pane', true).classed('fade', true);</script>