A-S: Text umrahmen in SVG

Hallo. Wie kann ich in einer SVG ein Rechteck um einen ganzen Text erstellen, wenn ich wegen variabler schrift nicht genau weis, wie breit er beim Betrachter wird? Ich bräuchte also eine Breite, welche sich an den Inhalt anpasst.

  1. Hallo A-S! Herzlich willkommen bei SELFHTML!

    Hallo. Wie kann ich in einer SVG ein Rechteck um einen ganzen Text erstellen, wenn ich wegen variabler schrift nicht genau weis, wie breit er beim Betrachter wird? Ich bräuchte also eine Breite, welche sich an den Inhalt anpasst.

    Das ist genau das Problem und der Unterschied zu HTML.

    In HTML bilden alle Elemente Blöcke mit einer Breite und Höhe. So kannst Du Text eine Farbe, aber auch eine Hintergrundfarbe oder einen Rand geben.

    In SVG besteht der Text nur aus den Zeichen oder Glyphen, denen du eine Füllung (fill) oder Randlinie (stroke) geben kannst. Der „Hintergrund“ existiert nicht, kann aber durch ein rect, das vorher (es gibt ja (noch) keinen z-index bei SVG) gezeichnet wird, mit Hintergrund und Rahmen um den Text gestaltet werden.

    Die Dimensionen müsstest du entweder ausprobieren oder mit Javascript berechnen.

    [EDIT] Hier bei SO gefunden: svg-get-text-element-width [/EDIT]

    Herzliche Grüße

    Matthias Scharwies

    --
    Ήταν διασκεδαστικό όσο κράτησε.
    Χρύσιππος ὁ Σολεύς, 220 π.Χ.
  2. Hallo A-S,

    Hallo. Wie kann ich in einer SVG ein Rechteck um einen ganzen Text erstellen, wenn ich wegen variabler schrift nicht genau weis, wie breit er beim Betrachter wird? Ich bräuchte also eine Breite, welche sich an den Inhalt anpasst.

    Wenn JavaScript eine Option ist, dann lässt sich mittels getComputedTextLength() die Textbreite ermitteln und dann auf das Rechteck anwenden, etwa mit diesem Ansatz:

    <?xml version="1.0" encoding="UTF-8"?>
    <svg xmlns="http://www.w3.org/2000/svg">
      <defs>
        <script type="text/javascript">
          document.addEventListener("DOMContentLoaded", function()
          {
            var textobj = document.getElementById("txt");
            var textbreite = textobj.getComputedTextLength().toFixed(1);
            var texthoehe = textobj.getAttribute("font-size");
            var rectobj = document.createElementNS("http://www.w3.org/2000/svg", "rect");
            rectobj.setAttribute("x", textobj.getAttribute("x") - 5);
            rectobj.setAttribute("y", textobj.getAttribute("y") - texthoehe);
            rectobj.setAttribute("height", (1.2 * texthoehe).toFixed(1));
            rectobj.setAttribute("width", (1.05 * textbreite).toFixed(1));
            rectobj.setAttribute("stroke", "#F00");
            rectobj.setAttribute("fill", "none");
            document.documentElement.insertBefore(rectobj, textobj);
          });
        </script>
      </defs>
      <text id="txt" x="20" y="40" font-size="24" font-family="sans-serif">Das ist der Text.</text>
      <!--
        Ergebnis:
        <rect x="15" y="16" height="28.8" width="180.7" stroke="#F00" fill="none"/>
      -->
    </svg>
    

    Grüße,
    Thomas

    1. @@ThomasM

      rectobj.setAttribute("height", (1.2 * texthoehe).toFixed(1));
      rectobj.setAttribute("width", (1.05 * textbreite).toFixed(1));
      

      Wo kommen die magic numbers her?

      🖖 Stay hard! Stay hungry! Stay alive! Stay home!

      --
      “Turn off CSS. If the page makes no sense, fix your markup.” —fantasai
      1. Hallo Gunnar,

        rectobj.setAttribute("height", (1.2 * texthoehe).toFixed(1));
        rectobj.setAttribute("width", (1.05 * textbreite).toFixed(1));
        

        Wo kommen die magic numbers her?

        Habe ich etwas experimentell mit einigen Schriftgrößen probiert. Kann man natürlich auch nach Belieben ändern oder anders bauen.

        Grüße,
        Thomas

    2. Servur!

      @Thomas Vielen Dank, ich hab's so ähnlich mal ins Wiki eingefügt:

      SVG/Tutorials/Text/mehrzeiliger_Text#Rahmen_um_Text_erzeugen

      Die Erklärung folgt noch!

      Herzliche Grüße

      Matthias Scharwies

      --
      Ήταν διασκεδαστικό όσο κράτησε.
      Χρύσιππος ὁ Σολεύς, 220 π.Χ.
    3. Hallo ThomasM,

      ich bin ja nicht so der SVG Spezi, darum sind das vielleicht dumme Fragen:

      • <script> in SVG? ECHT? Ich lade mir ggf. Script in die Seite, wenn ich von irgendwo ein SVG einbinde? Ich hab Angst! Oder sind DOM Zugriffe dieses Scripts auf die Inhalte des SVG gesandboxt? Die Spec schreibt: Any functions defined within any ‘script’ element have a "global" scope across the entire current document. - aber was ist für die Spec das Document?
      • Damit hängt der Scope der txt Id zusammen. Was ist, wenn ich dieses SVG zweimal auf die Seite lade, kollidieren die beiden IDs dann?
      • SVG ist XML, muss das Script da nicht in CDATA Kommentare eingeschlossen werden, so wie z.B. hier? Ok, die "bösen" Zeichen < > und & tauchen hier nicht auf, aber besser ist's wohl, oder?
      • Funktioniert das bei inline svg und einem als Image geladenen SVG gleichermaßen oder muss man da unterscheiden? Insbesondere bei der Frage: „Was ist das Document?“

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Servus!

        Hallo ThomasM,

        ich bin ja nicht so der SVG Spezi, darum sind das vielleicht dumme Fragen:

        • <script> in SVG? ECHT? Ich lade mir ggf. Script in die Seite, wenn ich von irgendwo ein SVG einbinde? Ich hab Angst! Oder sind DOM Zugriffe dieses Scripts auf die Inhalte des SVG gesandboxt? Die Spec schreibt: Any functions defined within any ‘script’ element have a "global" scope across the entire current document. - aber was ist für die Spec das Document?

        Nein, nur unter gewissen Umständen (mehr hier: SVG/Tutorials/SVG_und_JavaScript) Nur kurz: ein img darf kein script ausführen. Trotzdem haben aus diesem Grund viele CMS den Einsatz von SVG „verboten“. (Oder ein Plugin „reinigt“ das SVG von Scripten und externen Links auf weitere Seiten, die wieder andere Scripte aufrufen.)

        Viele alte Beispiele waren und sind Standalone-SVGs. Heute, da man SVGs ohne Plugin darstellen kann, würde ich nur noch inline-SVG verwenden (und evtl. dynamisch erzeugen). Ausnahme sind Logos, die ich als img einbinden würde.

        Auch im Wiki sind unsere Beispiele SVGs in HTML-Dokumenten.

        • SVG ist XML, muss das Script da nicht in CDATA Kommentare eingeschlossen werden, so wie z.B. hier? Ok, die "bösen" Zeichen < > und & tauchen hier nicht auf, aber besser ist's wohl, oder?

        Ja! Besser ist es imho aber die Zuständigkeiten zu trennen und das script-Element nicht irgendwo, sondern im Head oder am Ende des body-Elements zu notieren.

        • Funktioniert das bei inline svg und einem als Image geladenen SVG gleichermaßen oder muss man da unterscheiden? Insbesondere bei der Frage: „Was ist das Document?“

        siehe oben. Wenn der Wiki-Artikel nicht ausreichend ist, bitte erweitern!

        [EDIT] Eine Übersicht über die möglichen Einbindung(en) von SVG (und was dann jeweils möglich ist) findet sich hier:

        [/EDIT]

        Herzliche Grüße

        Matthias Scharwies

        --
        Ήταν διασκεδαστικό όσο κράτησε.
        Χρύσιππος ὁ Σολεύς, 220 π.Χ.
        1. Hallo Matthias,

          Viele alte Beispiele waren und sind Standalone-SVGs. Heute, da man SVGs ohne Plugin darstellen kann, würde ich nur noch inline-SVG verwenden (und evtl. dynmisch erzeugen). Ausnahme sind Logos, die ich als img einbinden würde.

          Es bietet sich auch weiterhin object für die SVG-Einbindung an.

          Über die HTML-/SVG-Schnittstelle kommt man dann von außen im JS des HTML-Dokuments an die SVG-Inhalte heran:

          // object-Element mit id="grafik" im HTML
          grafik = document.getElementById("grafik");
          
          // document-Objekt der eingebundenen Grafik
          svgdoc = grafik.contentDocument;
          
          

          Grüße,
          Thomas

      2. Hallo Rolf,

        • SVG ist XML, muss das Script da nicht in CDATA Kommentare eingeschlossen werden, so wie z.B. hier? Ok, die "bösen" Zeichen < > und & tauchen hier nicht auf, aber besser ist's wohl, oder?

        Ja, für die Nutzung der Zeichen < bzw. & ist das sinnvoll. > ist ja in XML nur kritisch, wenn der CDATA-Schließer ]]> selbst in einem CDATA-Abschnitt auftaucht, dann ]]&gt; nötig.

        Für größere Projekte bietet sich natürlich die Auslagerung von JS an.

        Scripting in SVG ist an sich ein alter Hut. Mein erstes SVG-Erklärdokument von 2002 nutzt bereits JS, um via mouseover unten den relevanten Code einzublenden.

        Grüße,
        Thomas