我正在SVG中绘制文字标签。我有一个固定的宽度(比如200px)。当文字太长时,我该如何修剪呢?
理想的解决方案还会添加文本被剪切的省略号(...)。但我也可以没有它。
答案 0 :(得分:26)
执行此操作的一种方法是使用textPath元素,因为从路径上掉落的所有字符都将自动剪切掉。请参阅SVG测试套件中的文本路径examples。
另一种方法是在svg文本元素上使用CSS3 text-overflow,例如here。 Opera 11支持这一点,但您可能会发现其他浏览器目前仅支持html元素。
你也可以测量文本字符串并自己用脚本插入省略号,我建议在文本元素上使用getSubStringLength方法,增加nchars参数,直到找到合适的长度。
答案 1 :(得分:21)
使用d3库
用于溢出文本的包装函数:
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();
}
}
用法:
text.append('tspan').text(function(d) { return d.name; }).each(wrap);
答案 2 :(得分:17)
实施Erik的第三个建议我想出了类似的东西:
//places textString in textObj, adds an ellipsis if text can't fit in width
function placeTextWithEllipsis(textObj,textString,width){
textObj.textContent=textString;
//ellipsis is needed
if (textObj.getSubStringLength(0,textString.length)>=width){
for (var x=textString.length-3;x>0;x-=3){
if (textObj.getSubStringLength(0,x)<=width){
textObj.textContent=textString.substring(0,x)+"...";
return;
}
}
textObj.textContent="..."; //can't place at all
}
}
似乎可以做到这一点:)
答案 3 :(得分:4)
@ user2846569告诉我该怎么做(是的,使用d3.js)。但是,我必须做一些改变才能工作:
function wrap( d ) {
var self = d3.select(this),
textLength = self.node().getComputedTextLength(),
text = self.text();
while ( ( textLength > self.attr('width') )&& text.length > 0) {
text = text.slice(0, -1);
self.text(text + '...');
textLength = self.node().getComputedTextLength();
}
}
svg.append('text')
.append('tspan')
.text(function(d) { return d; })
.attr('width', 200 )
.each( wrap );
答案 4 :(得分:1)
尝试这个,我在图表库中使用此功能:
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 + "...";
}
}
}
答案 5 :(得分:0)
我的方法类似于OpherV,但我尝试使用JQuery
function getWidthOfText(text, fontSize, fontFamily) {
var span = $('<span></span>');
span.css({
'font-family': fontFamily,
'font-size' : fontSize
}).text(text);
$('body').append(span);
var w = span.width();
span.remove();
return w;
}
function getStringForSize(text, desiredSize, fontSize, fontFamily) {
var curSize = getWidthOfText(text, fontSize, fontFamily);
if(curSize > size)
{
var curText = text.substring(0,text.length-5) + '...';
return getStringForSize(curText, size, fontSize, fontFamily);
}
else
{
return text;
}
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
现在,在致电getStringForSize('asdfasdfasdfasdfasdfasdf', 110, '13px','OpenSans-Light')
时,您将获得&#34; asdfasdfasdfasd ......&#34;
答案 6 :(得分:0)
linearGradient元素可用于生成纯SVG解决方案。此示例淡出截断的文本(无省略号):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<defs>
<linearGradient gradientUnits="userSpaceOnUse" x1="0" x2="200" y1="0" y2="0" id="truncateText">
<stop offset="90%" stop-opacity="1" />
<stop offset="100%" stop-opacity="0" />
</linearGradient>
<linearGradient id="truncateLegendText0" gradientTransform="translate(0)" xlink:href="#truncateText" />
<linearGradient id="truncateLegendText1" gradientTransform="translate(200)" xlink:href="#truncateText" />
</defs>
<text fill="url(#truncateLegendText0)" font-size="50" x="0" y="50">0123456789</text>
<text fill="url(#truncateLegendText1)" font-size="50" x="200" y="150">0123456789</text>
</svg>
(我必须使用线性渐变来解决这个问题,因为我使用的SVG渲染器不支持textPath解决方案。)
答案 7 :(得分:0)
有几种使用d3和循环的变体来搜索适合的较小文本。无需循环即可实现,并且工作速度更快。 textNode-d3节点。
clipText(textNode, maxWidth, postfix) {
const textWidth = textNode.getComputedTextLength();
if (textWidth > maxWidth) {
let text = textNode.textContent;
const newLength = Math.round(text.length * (1 - (textWidth - maxWidth) / textWidth));
text = text.substring(0, newLength);
textNode.textContent = text.trim() + postfix;
}
}