29

我正在使用 Raphael 库创建一个 SVG 文本框,并用从 XML 文档中提取的动态字符串填充它。

有时,这个字符串比我放置文本框的画布长,所以我需要限制框的宽度,这本身会强制换行(我找不到任何证据表明这是可能的)或确保在一定数量的字符之后插入'\n'换行符。

那么(1)这是最好的选择吗?(2)我该怎么做?

4

5 回答 5

47

文本换行没有属性,但您可以使用一个简单的技巧。一次向文本对象添加一个单词,当它变得太宽时,添加换行符。您可以使用 getBBox() 函数来确定宽度。基本上,您模仿的是老式打字机。这是一些可以为您执行此操作的代码示例。你可以很容易地把它变成一个简单的函数,它接受文本和宽度。

var r = Raphael(500, 500);
var t = r.text(100, 100).attr('text-anchor', 'start');
var maxWidth = 100;

var content = "Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate. ";
var words = content.split(" ");

var tempText = "";
for (var i=0; i<words.length; i++) {
  t.attr("text", tempText + " " + words[i]);
  if (t.getBBox().width > maxWidth) {
    tempText += "\n" + words[i];
  } else {
    tempText += " " + words[i];
  }
}

t.attr("text", tempText.substring(1));
于 2010-06-30T21:14:42.980 回答
9

thanks for the answer. However, I found that I needed a few adjustments to work for me:

function textWrap(t, width) {
    var content = t.attr("text");
    var abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    t.attr({
      'text-anchor' : 'start',
      "text" : abc
    });
    var letterWidth = t.getBBox().width / abc.length;
    t.attr({
        "text" : content
    });

    var words = content.split(" ");
    var x = 0, s = [];
    for ( var i = 0; i < words.length; i++) {

        var l = words[i].length;
        if (x + (l * letterWidth) > width) {
            s.push("\n");
            x = 0;
        }
        x += l * letterWidth;
        s.push(words[i] + " ");
    }
    t.attr({
        "text" : s.join("")
    });
}

The changes were:

  • the comparison needed to use (l * letterwidth) ... not just l
  • the if/else changed to just an if - so that a line break will always set X to 0
  • and always add the new l * letterwidth to the x value

hope this helps.

于 2012-03-27T23:56:02.633 回答
3

对于大量文本(firefox 11),mark 的解决方案很慢。我认为这是因为文本被重新渲染多次以获得 BBOX。以下函数对大量文本更有效,但可能不太准确(来自raphaelmarkup 项目的代码):

/**
 * @param t a raphael text shape
 * @param width - pixels to wrapp text width
 * modify t text adding new lines characters for wrapping it to given width.
 */
rm._textWrapp = function(t, width) {
    var content = t.attr("text");
    var abc="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    t.attr({'text-anchor': 'start', "text": abc});
    var letterWidth=t.getBBox().width / abc.length;
    t.attr({"text": content});
    var words = content.split(" "), x=0, s=[];
    for ( var i = 0; i < words.length; i++) {
        var l = words[i].length;
        if(x+l>width) {
            s.push("\n")
            x=0;
        }
        else {
            x+=l*letterWidth;
        }
        s.push(words[i]+" ");
    }
    t.attr({"text": s.join("")});
};
于 2012-03-22T00:13:27.213 回答
0

好吧,我稍微调整一下就解决了

var words = server.split( " " );
var length = words.length;
var temp_text = "";

for( var i = 0; i < length; i++ ) {
    temp_text = temp_text + ' ' + words[i];
    t.attr( "text", temp_text );

    if( t.getBBox().width > width ) {
        temp_text = temp_text.replace(/( *)(\w+)$/, "\n$2");
    }
}

t.attr( "text", temp_text.trim() );
于 2013-09-11T16:06:46.047 回答
0

我知道现在有点晚了,但你可能对我的Raphael-paragraph项目感兴趣,它会自动执行此操作。

Raphael-paragraph 允许您创建具有最大宽度和高度限制、行高和文本样式配置的自动换行多行文本。如果它们超出垂直边界,它可以将长词连字符并截断它们。它仍然是 beta-ish,需要大量优化,但它应该可以满足您的目的。

GitHub 页面上提供了使用示例和文档。

于 2015-05-24T22:54:06.410 回答