wake-up-neo.net

Wie kann man die SVG-Textfeldbreite bestimmen oder Zeilenumbrüche nach 'x' erzwingen?

Ich erstelle ein SVG-Textfeld mit der Raphael-Bibliothek und fülle es mit einer dynamischen Zeichenfolge, die aus einem XML-Dokument extrahiert wird.

Manchmal ist diese Zeichenfolge länger als die Zeichenfläche, auf der ich das Textfeld platziere. Daher muss ich entweder die Breite des Felds begrenzen, wodurch die Zeilenumbrüche erzwungen werden (ich kann keinen Beweis dafür finden, dass dies möglich ist). OR stellen Sie sicher, dass nach einer bestimmten Anzahl von Zeichen ein '\ n' Zeilenumbruch eingefügt wird.

Also (1) ist dies die beste Option? Und (2) wie würde ich das machen?

28
Jack Roscoe

Es gibt kein Attribut für den Textumbruch, aber einen einfachen Trick, den Sie verwenden können. Fügen Sie einem Textobjekt jeweils ein Wort hinzu, und fügen Sie einen Zeilenvorschub hinzu, wenn es zu breit wird. Mit der Funktion getBBox () können Sie die Breite bestimmen. Grundsätzlich emulieren Sie eine altmodische Schreibmaschine. Hier ist ein Beispiel für Code, der dies für Sie erledigt. Sie können dies leicht in eine einfache Funktion umwandeln, die den Text und die Breite übernimmt.

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));
46
Mark

danke für die Antwort. Ich stellte jedoch fest, dass ich einige Anpassungen benötigte, um für mich zu arbeiten:

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

Die Änderungen waren:

  • der Vergleich benötigt, um (l * letterwidth) zu verwenden ... nicht nur l
  • das if/else wurde in nur ein if geändert, sodass ein Zeilenumbruch immer X auf 0 setzt
  • und füge immer die neue l * -Breite zum x-Wert hinzu

hoffe das hilft.

9
Evan

die Lösung von mark ist für große Textmengen langsam (Firefox 11). Ich denke, das liegt daran, dass der Text mehrmals gerendert wird, um BBOX zu erhalten. Die folgende Funktion ist effizienter für große Textmengen, aber möglicherweise weniger genau (Code aus raphaelmarkup project ):

/**
 * @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

Ich weiß, dass es jetzt etwas verspätet ist, aber Sie könnten an meinem Raphael-Absatz Projekt interessiert sein, das dies automatisch erledigt.

Mit Raphael-paragraph können Sie automatisch umbrochenen mehrzeiligen Text mit maximalen Einschränkungen für Breite und Höhe, Zeilenhöhe und Textstilkonfiguration erstellen. Es kann lange Wörter trennen und abschneiden, wenn sie vertikale Grenzen überschreiten. Es ist immer noch ziemlich Beta-fähig und erfordert eine Menge Optimierung, aber es sollte für Ihre Zwecke funktionieren.

Anwendungsbeispiele und Dokumentation finden Sie auf der GitHub-Seite.

0

Nun, ich habe es gelöst, indem ich es ein wenig verändert habe

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