Hintergrundfarbe des Textes in SVG

99

Ich möchte den Hintergrund von SVG textähnlich wie background-colorin CSS färben

Ich konnte nur Unterlagen zu finden fill , die den Text selbst färbt

Ist es überhaupt möglich?

Nick Ginanto
quelle
Können Sie Ihren Code bisher teilen?
gotohales
stackoverflow.com/questions/12260370/… zeigt auch, wie dies mithilfe von Filtern gemacht wird.
Erik Dahlström
1
@RobertLongson Das Schließen dieser Frage als Duplikat, wenn sie 2 Jahre vor der anderen gestellt wurde, scheint falsch zu sein, insbesondere wenn die einzige Antwort Ihre ist.
Balthazar
@ Aperçu: Das Alter einer Frage ist nicht der Hauptfaktor bei der Auswahl eines doppelten Ziels, siehe zum Beispiel hier .
Hupen

Antworten:

92

Nein, das ist nicht möglich. SVG-Elemente haben keine background-... Präsentationsattribute .

Um diesen Effekt zu simulieren, können Sie ein Rechteck hinter das Textattribut mit fill="green"oder etwas Ähnliches (Filter) zeichnen . Mit JavaScript können Sie Folgendes tun:

var ctx = document.getElementById("the-svg"),
textElm = ctx.getElementById("the-text"),
SVGRect = textElm.getBBox();

var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
    rect.setAttribute("x", SVGRect.x);
    rect.setAttribute("y", SVGRect.y);
    rect.setAttribute("width", SVGRect.width);
    rect.setAttribute("height", SVGRect.height);
    rect.setAttribute("fill", "yellow");
    ctx.insertBefore(rect, textElm);
sluijs
quelle
8
Das oder verwenden Sie einen SVG-Filter (feFlood + feComposite) für den Text. Siehe etwas ähnliche Frage stackoverflow.com/questions/12260370/… .
Erik Dahlström
3
Diese Lösung mit getBBox () funktioniert zwar einwandfrei, kann jedoch recht langsam sein, wenn eine große Anzahl von Berechnungen durchgeführt werden muss. Das Problem bei der Verwendung eines SVG-Filters (feFlood + feComposite) ist, dass der Text etwas gezackt herauskommt. Habe unten eine einfache, aber hackige Lösung angeboten.
dbarton_uk
Verwenden Sie lieber textElm = document.getElementById ("the-text") anstelle von textElm = ctx.getElementById ("the-text")?
Simon Hi
Wie kal ich die gleiche getBBox-Funktion in nodeJS verwende
Ali
76

Sie können einen Filter verwenden, um den Hintergrund zu generieren.

<svg width="100%" height="100%">
  <defs>
    <filter x="0" y="0" width="1" height="1" id="solid">
      <feFlood flood-color="yellow"/>
      <feComposite in="SourceGraphic" operator="xor" />
    </filter>
  </defs>
<text filter="url(#solid)" x="20" y="50" font-size="50">solid background</text>
</svg>

Robert Longson
quelle
1
Was bedeutet "SourceGraphic" hier? Verursacht "url (#solid)" tatsächlich einen zusätzlichen Webzugriff?
Ben Slade
7
Text ist hier verschwommen :(
Teran
5
Kann yo den Hintergrund geben padding ?
vsync
2
Ich liebe diese Lösung theoretisch, kann aber bestätigen, dass der Text verschwommen ist. Es scheint, als würde der Filter das Anti-Aliasing unterbrechen.
Paulmelnikow
2
Hinzufügen operator="xor"zu feComposite, um unscharfen Text zu vermeiden. @ RobertLongson @teran @ paulmelnikow @bill
Saeid Zebardast
19

Die Lösung, die ich verwendet habe, ist:

<svg>
  <line x1="100" y1="100" x2="500" y2="100" style="stroke:black; stroke-width: 2"/>    
  <text x="150" y="105" style="stroke:white; stroke-width:0.6em">Hello World!</text>
  <text x="150" y="105" style="fill:black">Hello World!</text>  
</svg>

Es wird ein doppeltes Textelement mit Strich- und Strichbreitenattributen platziert. Der Strich sollte mit der Hintergrundfarbe übereinstimmen, und die Strichbreite sollte gerade groß genug sein, um einen "Splodge" zu erstellen, auf den der eigentliche Text geschrieben werden kann.

Ein bisschen wie ein Hack und es gibt potenzielle Probleme, aber funktioniert für mich!

dbarton_uk
quelle
1
Ich fand diese Lösung am einfachsten.
Morgan Wilde
Bestätigt dies als einfachste Lösung
Scipper
Druckt auch gut, wenn die Filterlösung beim Drucken sehr verschwommen war.
David Hunt
17

Nein, Sie können SVG-Elementen keine Hintergrundfarbe hinzufügen. Sie können dies programmgesteuert mit d3 tun .

var text = d3.select("text");
var bbox = text.node().getBBox();
var padding = 2;
var rect = self.svg.insert("rect", "text")
    .attr("x", bbox.x - padding)
    .attr("y", bbox.y - padding)
    .attr("width", bbox.width + (padding*2))
    .attr("height", bbox.height + (padding*2))
    .style("fill", "red");
nnattawat
quelle
3
Das funktioniert nicht; Es ändert nur die Farbe des Textes, nicht die Hintergrundfarbe.
David J.
Setzen Sie den Text in einem div oder Spanne und gelten Styling zu je nachdem , welcher der beiden letzten Sie verwendet haben.
Arif Burhan
4

Antwort von Robert Longson (@RobertLongson) mit Änderungen:

<svg width="100%" height="100%">
  <defs>
    <filter x="0" y="0" width="1" height="1" id="solid">
      <feFlood flood-color="yellow"/>
      <feComposite in="SourceGraphic" operator="xor"/>
    </filter>
  </defs>
  <text filter="url(#solid)" x="20" y="50" font-size="50"> solid background </text>
  <text x="20" y="50" font-size="50">solid background</text>
</svg>

und wir haben keine Unschärfe und keine schwere "getBBox" :) Das Auffüllen erfolgt durch Leerzeichen im Textelement mit Filter. Es hat bei mir funktioniert

Roman Belov
quelle
2

Dies ist mein Lieblings-Hack (nicht sicher, ob es funktionieren sollte). Es verweist auf ein Element, das noch nicht angezeigt wird, und es funktioniert ziemlich gut

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 620 40" preserveAspectRatio="xMidYMid meet">
    <defs>
        <filter x="-0.02" y="0" width="1.04" height="1.1" id="removebackground">
            <feFlood flood-color="#00ffff"/>
        </filter>
    </defs>

    <!--Draw the text--> 
    <use xlink:href="#mygroup" filter="url(#removebackground)" />
    <g id="mygroup">
        <text id="text1" x="9" y="20" style="text-anchor:start;font-size:14px;">custom text with background</text>  
        <line x1="200" y1="18" x2="200" y2="36" stroke="#000" stroke-width="5"/> 
        <line x1="120" y1="27" x2="203" y2="27" stroke="#000" stroke-width="5"/> 
    </g>
</svg>

Calimero100582
quelle
2

Sie können Filter mit dem Text kombinieren.

<!DOCTYPE html>
<html>
  <head>
    <meta charset=utf-8 />
    <title>SVG colored patterns via mask</title>
  </head>
  <body>
    <svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <filter x="0" y="0" width="1" height="1" id="bg-text">
          <feFlood flood-color="white"/>
          <feComposite in="SourceGraphic" operator="xor" />
        </filter>
      </defs>
	  <!-- something has already existed -->
    <rect fill="red" x="150" y="20" width="100" height="50" />
    <circle cx="50"  cy="50" r="50" fill="blue"/>
      
      <!-- Text render here -->
      <text filter="url(#bg-text)" fill="black" x="20" y="50" font-size="30">text with color</text>
      <text fill="black" x="20" y="50" font-size="30">text with color</text>
    </svg>
  </body>
</html> 

Vu Phan
quelle
1

Wenn Sie sich fragen, wie Sie ein Textelement mit einem Hintergrund wie in der Antwort von Robert auffüllen sollen, gehen Sie wie folgt vor:

  <svg>
    <defs>
      <filter x="-0.1" y="-0.1" width="1.2" height="1.2" id="solid">
        <feFlood flood-color="#171717"/>
        <feComposite in="SourceGraphic" operator="xor" />
      </filter>
    </defs>
    <text filter="url(#solid)" x="20" y="50" font-size="50">Hello</text>
  </svg>

Im obigen Beispiel können die x- und y- Positionen des Filters wie gewohnt verwendet werden transform: translate(-10%, -10%), und die Werte für Breite und Höhe können als 120%und gelesen werden 120%. Also haben wir den Hintergrund um 20% vergrößert und um -10% versetzt, sodass der Hintergrund jetzt auf jeder Seite des Textes um 10% größer ist.

Momciloo
quelle
0

Die vorherigen Antworten beruhten auf der Verdoppelung des Textes und es fehlte genügend Leerzeichen.

Durch die Verwendung von atopund &nbsp;konnte ich die gewünschten Ergebnisse erzielen.

Dieses Beispiel enthält auch Pfeile, ein häufiger Anwendungsfall für SVG-Textbeschriftungen:

<svg viewBox="-105 -40 210 234">
<title>Size Guide</title>
<defs>
    <filter x="0" y="0" width="1" height="1" id="solid">
        <feFlood flood-color="white"></feFlood>
        <feComposite in="SourceGraphic" operator="atop"></feComposite>
    </filter>
    <marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
        <path d="M 0 0 L 10 5 L 0 10 z"></path>
    </marker>
</defs>
<g id="garment">
    <path id="right-body" fill="none" stroke="black" stroke-width="1" stroke-linejoin="round" d="M0 0 l30 0 l0 154 l-30 0"></path>
    <path id="right-sleeve" d="M30 0 l35 0 l0 120 l-35 0" fill="none" stroke-linejoin="round" stroke="black" stroke-width="1"></path>
    <use id="left-body" href="#right-body" transform="scale(-1,1)"></use>
    <use id="left-sleeve" href="#right-sleeve" transform="scale(-1,1)"></use>
    <path id="collar-right-top" fill="none" stroke="black" stroke-width="1" stroke-linejoin="round" d="M0 -6.5 l11.75 0 l6.5 6.5"></path>
    <use id="collar-left-top" href="#collar-right-top" transform="scale(-1,1)"></use>
    <path id="collar-left" fill="white" stroke="black" stroke-width="1" stroke-linejoin="round" d="M-11.75 -6.5 l-6.5 6.5 l30 77 l6.5 -6.5 Z"></path>
    <path id="front-right" fill="white" stroke="black" stroke-width="1" d="M18.25 0 L30 0 l0 154 l-41.75 0 l0 -77 Z"></path>
    <line x1="0" y1="0" x2="0" y2="154" stroke="black" stroke-width="1" stroke-dasharray="1 3"></line>
    <use id="collar-right" href="#collar-left" transform="scale(-1,1)"></use>
</g>
<g id="dimension-labels">
    <g id="dimension-sleeve-length">
        <line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="85" y1="0" x2="85" y2="120" stroke="black" stroke-width="1"></line>
        <text font-size="10" filter="url(#solid)" fill="black" x="85" y="60" class="dimension" text-anchor="middle" dominant-baseline="middle"> 120 cm</text>
    </g>
    <g id="dimension-length">
        <line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-85" y1="0" x2="-85" y2="154" stroke="black" stroke-width="1"></line>
        <text font-size="10" filter="url(#solid)" fill="black" x="-85" y="77" text-anchor="middle" dominant-baseline="middle" class="dimension"> 154 cm</text>
    </g>
    <g id="dimension-sleeve-to-sleeve">
        <line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-65" y1="-20" x2="65" y2="-20" stroke="black" stroke-width="1"></line>
        <text font-size="10" filter="url(#solid)" fill="black" x="0" y="-20" text-anchor="middle" dominant-baseline="middle" class="dimension">&nbsp;130 cm&nbsp;</text>
    </g>
    <g title="Back Width" id="dimension-back-width">
        <line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-30" y1="174" x2="30" y2="174" stroke="black" stroke-width="1"></line>
        <text font-size="10" filter="url(#solid)" fill="black" x="0" y="174" text-anchor="middle" dominant-baseline="middle" class="dimension">&nbsp;60 cm&nbsp;</text>
    </g>
</g>
</svg>
Henrys Katze
quelle
-1

Sie können Ihrem Text Stil hinzufügen:

  style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); 
    text-shadow: rgb(255, 255, 255) -2px -2px 0px, rgb(255, 255, 255) -2px 2px 0px, 
     rgb(255, 255, 255) 2px -2px 0px, rgb(255, 255, 255) 2px 2px 0px;"

Weiß in diesem Beispiel. Funktioniert nicht im IE :)

Jan Pi
quelle