我正在使用从ericsoco借来的函数来将文本换行超出SVG元素中的某个宽度。该网页有一个(Bootstrap)标签界面,可以连接许多SVG元素。文本换行功能在第一个选项卡上完美运行,但在第二个选项卡上不运行。不知何故,tab函数似乎干扰了文本换行功能。
网页位于https://manypossibilities.net/spectrum-chart/index.html 和完整的源代码可以在 https://github.com/stevesong/spectrum-chart/blob/master/index.html 和https://github.com/stevesong/spectrum-chart/blob/master/byCountry.js
您可以看到名称为Telecom Namibia的名称在第一个选项卡上正确包装但在第二个选项卡上没有。
自动换行功能如下:
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);
}
}
});
}
答案 0 :(得分:1)
更新:我不再按照以下详细说明进行操作;在大型项目上跟踪活跃的div
和svg
太难了。相反,我使用它:
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>