web-dev-qa-db-ja.com

SVGテキストボックスの幅を決定する方法、または「x」文字の後に改行を強制する方法は?

Raphaelライブラリを使用してSVGテキストボックスを作成し、XMLドキュメントから抽出された動的な文字列を入力しています。

この文字列は、テキストボックスを配置するキャンバスよりも長い場合があるため、ボックスの幅を制限して、それ自体で改行を強制する必要があります(これが可能であるという証拠は見つかりません)OR特定の文字数の後に '\ n'改行が挿入されていることを確認します。

それで(1)これは最良の選択肢ですか?そして(2)どうすればこれを行うことができますか?

28
Jack Roscoe

テキストの折り返しの属性はありませんが、使用できる簡単なトリックがあります。テキストオブジェクトに一度に1つの単語を追加し、幅が広すぎる場合は改行を追加します。 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));
47
Mark

答えてくれてありがとう。しかし、私は私のために働くためにいくつかの調整が必要であることがわかりました:

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("")
    });
}

変更点は次のとおりです。

  • 使用するために必要な比較(l *文字幅)... lだけでなく
  • if/elseがif-に変更されたため、改行によってXが常に0に設定されます。
  • 常に新しいl *文字幅をx値に追加します

お役に立てれば。

9
Evan

マークの解決策は、大量のテキストに対しては遅いです(firefox11)。これは、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("")});
};
3
cancerbero

今は少し遅れていることはわかっていますが、これを自動的に行う私の Raphael-paragraph プロジェクトに興味があるかもしれません。

Raphael-paragraphを使用すると、最大の幅と高さの制約、行の高さ、およびテキストスタイルの構成を使用して自動折り返しの複数行テキストを作成できます。長い単語をハイフンでつなぎ、垂直方向の境界を超えた場合は切り捨てることができます。それはまだかなりベータっぽく、多くの最適化を必要としますが、それはあなたの目的のために働くはずです。

使用例とドキュメントはGitHubページにあります。

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() );
0
Carlos