在我们通过 d3 操作的 SVG 中需要文本元素的情况并不少见,例如分类刻度标签。这有点不幸,因为<text>SVG 中的元素不是最好的......渲染的字体大小通常略大于人们认为字体应该占用的大小。例如,如果选择宽度/高度比为 0.6 的等宽字体(例如,如果字体大小为 12px,则字符的宽度应为 7.2px),则元素的计算边界矩形可能为 14.2px x n *8px其中n是字符数。
使问题进一步复杂化的事实是,人们通常使用非等宽字体。
很容易截断一个“太长”的字符串
string.slice(0, numChars-3)+'...'
Run Code Online (Sandbox Code Playgroud)
但是知道适合固定宽度的正确字符数似乎并非易事。
function truncateText(t, text, space) {
// make sure it is a string
text = String(text)
// set text
t.text(text)
// get space it takes up
var rect = t.node().getBoundingClientRect()
while (Math.max(rect.width, rect.height) > space) {
text = text.slice(0, text.length - 1)
t.text(text + '...')
rect = t.node().getBoundingClientRect()
if (text.length == 0) break
}
}
Run Code Online (Sandbox Code Playgroud)
上面的函数需要一个 d3.selection,文本和文本应该适合的空间。通过不断操作 DOM,我们可以得到完美的拟合,但是这在计算上非常昂贵。
为了澄清,为了在固定空间中放置文本,我的意思是,如果我有一个 string var string = "this is my very long string",我希望呈现字符串的方向(从左到右,即我们正在查看字符串长度)以适应固定空间(例如var fixedSpace = 100 //px)
上面的 truncate text 函数只适用于少数几个字符串,但是如果有很多字符串调用这个函数,它就会变得滞后。
当然,我们可以通过选择最长的字符串进行优化,在该字符串上计算 truncateText,然后取字符数作为结果(尽管这仍然有些问题,因为并非所有字符都具有相同的宽度)。
有没有更有效的方法来使用 d3 将文本截断为固定空间
我同意你建议的方法在计算上是昂贵的,但这是我能想到的唯一一种方法。但是,如果您只是偶尔运行它(即仅在页面加载时运行,而不是在鼠标悬停时运行),那么它应该不会太糟糕,具体取决于您应用它的文本元素的数量。
您可能想尝试将您的方法的性能与Mike Bostock 示例中的方法进行比较,该方法使用node().getComputedTextLength()代替node().getBoundingClientRect()并按单词分解文本:
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
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);
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
PS/ 有一种CSS 技术可以用省略号截断文本,但不幸的是它在 SVG 中不起作用:(
| 归档时间: |
|
| 查看次数: |
2099 次 |
| 最近记录: |