Add ellipses to overflowing text in SVG?
我用的是
1 2 3 4 5 6 7 8 | .ai-ellipsis { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; -o-text-overflow: ellipsis; -moz-binding: url(<q>assets/xml/ellipsis.xml#ellipsis</q>); } |
这是我的SVG:
1 2 3 4 | <g class="bar" transform="translate(0,39)"> <text class="label" x="-3" y="6.5" dy=".35em" text-anchor="start">Construction</text> <rect height="13" width="123"></rect> </g> |
号
生成如下:
1 2 3 4 5 6 | barEnter.append("text").attr("class","label") .attr("x", -3).attr("y", function() { return y.rangeBand() / 2}) .attr("dy",".35em").attr("text-anchor","start") .text(function(d) { return d.Name; }); |
当前文本溢出并与rect元素重叠。
我有没有办法说"如果文本超过了某个宽度,裁剪它并添加省略号"?
用于溢出文本的包装函数:
1 2 3 4 5 6 7 8 9 10 | function wrap() { var self = d3.select(this), textLength = self.node().getComputedTextLength(), text = self.text(); while (textLength > (width - 2 * padding) && text.length > 0) { text = text.slice(0, -1); self.text(text + '...'); textLength = self.node().getComputedTextLength(); } } |
用途:
1 | text.append('tspan').text(function(d) { return d.name; }).each(wrap); |
号
我不知道SVG有一个等价的CSS类,但是您可以使用
请参阅此处以获取完整的示例。
我实现了一个不依赖于d3的本机函数,该函数实现了三种方式的回退:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | function textEllipsis(el, text, width) { if (typeof el.getSubStringLength !=="undefined") { el.textContent = text; var len = text.length; while (el.getSubStringLength(0, len--) > width) {} el.textContent = text.slice(0, len) +"..."; } else if (typeof el.getComputedTextLength !=="undefined") { while (el.getComputedTextLength() > width) { text = text.slice(0,-1); el.textContent = text +"..."; } } else { // the last fallback while (el.getBBox().width > width) { text = text.slice(0,-1); // we need to update the textContent to update the boundary width el.textContent = text +"..."; } } } |
。
1 2 3 4 | function trimText(text, threshold) { if (text.length <= threshold) return text; return text.substr(0, threshold).concat("..."); } |
使用此函数设置SVG节点文本。阈值的值(如20)取决于您。这意味着您将从节点文本中最多显示20个字符。超过20个字符的所有文本将被剪裁并在剪裁文本的末尾显示"…"。
用法,例如:
1 2 | var self = this; nodeText.text(x => self.trimText(x.name, 20)) // nodeText it's the text element of the SVG node |
。
只是更新了由用户2846569提出的wrap函数。getComputedTextLength()通常非常慢,因此…
编辑
我努力应用了用户2846569的建议,并制作了一个"二进制"搜索版本,具有一定的校准和参数化精度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 'use strict'; var width = 2560; d3.select('svg').attr('width', width); // From http://stackoverflow.com/questions/10726909/random-alpha-numeric-string-in-javascript function randomString(length, chars) { var result = ''; for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)]; return result; } function wrap() { var self = d3.select(this), textWidth = self.node().getComputedTextLength(), // Width of text in pixel. initialText = self.text(), // Initial text. textLength = initialText.length, // Length of text in characters. text = initialText, precision = 10, //textWidth / width, // Adjustable precision. maxIterations = 100; // width; // Set iterations limit. while (maxIterations > 0 && text.length > 0 && Math.abs(width - textWidth) > precision) { text = /*text.slice(0,-1); =*/(textWidth >= width) ? text.slice(0, -textLength * 0.15) : initialText.slice(0, textLength * 1.15); self.text(text + '...'); textWidth = self.node().getComputedTextLength(); textLength = text.length; maxIterations--; } console.log(width - textWidth); } var g = d3.select('g'); g.append('text').append('tspan').text(function(d) { return randomString(width, 'a'); }).each(wrap); |
在jsFiddle上查看。