Colore di sfondo del testo in SVG


101

Voglio colorare lo sfondo di svg in modo textsimile a background-colorcss

Sono stato in grado di trovare solo documentazione su fill, che colora il testo stesso

È anche possibile?


Puoi condividere il tuo codice finora?
gotohales


stackoverflow.com/questions/12260370/… mostra anche come farlo utilizzando i filtri.
Erik Dahlström

1
@RobertLongson Chiudere questa domanda come duplicata quando è stata posta 2 anni prima dell'altra sembra sbagliato, specialmente quando l'unica risposta è la tua.
Balthazar

@ Aperçu: L'età di una domanda non è il fattore principale nella scelta di un target duplicato, vedi ad esempio qui .
clacson

Risposte:


93

No, non è possibile, gli elementi SVG non hanno background-... attributi di presentazione .

Per simulare questo effetto puoi disegnare un rettangolo dietro l'attributo text con fill="green"o qualcosa di simile (filtri). Usando JavaScript puoi fare quanto segue:

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

8
Oppure usa un filtro svg (feFlood + feComposite) sul testo. Vedi domanda leggermente simile stackoverflow.com/questions/12260370/… .
Erik Dahlström

3
Questa soluzione che utilizza getBBox (), sebbene funzioni perfettamente, può essere piuttosto lenta quando è necessario eseguire un gran numero di calcoli. Il problema con l'utilizzo di un filtro svg (feFlood + feComposite) è che il testo risulta leggermente frastagliato. Ho offerto una soluzione semplice ma complicata di seguito.
dbarton_uk

Meglio usare textElm = document.getElementById ("the-text") invece di textElm = ctx.getElementById ("the-text")?
Simon Ciao

Come cal uso la stessa funzione getBBox in nodeJS
Ali

77

È possibile utilizzare un filtro per generare lo sfondo.

<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>


1
Cosa significa "SourceGraphic" qui? "Url (#solid)" causa effettivamente un accesso web aggiuntivo?
Ben Slade

7
il testo è sfocato qui :(
teran

5
Puoi dare il riempimento dello sfondo ?
vsync

2
Adoro questa soluzione in teoria, ma posso confermare che il testo è sfocato. Sembra che il filtro rompa l'anti-aliasing.
paulmelnikow

2
Aggiungi operator="xor"a feCompositeper evitare testo sfocato. @RobertLongson @teran @paulmelnikow @bill
Saeid Zebardast

20

La soluzione che ho usato è:

<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>

Viene posizionato un elemento di testo duplicato, con gli attributi di tratto e larghezza del tratto. Il tratto dovrebbe corrispondere al colore di sfondo e la larghezza del tratto dovrebbe essere appena sufficiente per creare uno "splodge" su cui scrivere il testo effettivo.

Un po 'un trucco e ci sono potenziali problemi, ma funziona per me!


1
Ho trovato questa soluzione la più semplice.
Morgan Wilde

Confermata questa soluzione più semplice
scipper

Stampa bene anche dove la soluzione del filtro era molto sfocata durante la stampa.
David Hunt

17

No, non puoi aggiungere il colore di sfondo agli elementi SVG. Puoi farlo in modo programmatico con d3 .

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

3
Questo non funziona; cambia solo il colore del testo, non il colore di sfondo.
David J.

Racchiudi il testo in un div o in uno span e applica lo stile a qualsiasi degli ultimi due che hai usato.
Arif Burhan

Questo post lo spiega bene: cambridge-intelligence.com/…
exchange


4

Risposta di Robert Longson (@RobertLongson) con modifiche:

<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>

e non abbiamo né sfocature né pesanti "getBBox" :) Il riempimento è fornito da spazi bianchi nell'elemento di testo con filtro. Ha funzionato per me


2

questo è il mio trucco preferito (non sono sicuro che dovrebbe funzionare). Si riferisce a un elemento che non è ancora visualizzato e funziona abbastanza bene

<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>


2

Puoi combinare il filtro con il testo.

<!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> 


1

Per coloro che si chiedono come applicare il riempimento a un elemento di testo quando ha uno sfondo come nella risposta di Robert , procedi come segue:

  <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>

Nell'esempio sopra, le posizioni x e y del filtro possono essere utilizzate come si transform: translate(-10%, -10%)farebbe, e i valori di larghezza e altezza possono essere letti come 120%e 120%. Quindi abbiamo ingrandito lo sfondo del 20% e compensato il -10%, quindi lo sfondo ora è più grande del 10% su ciascun lato del testo.


0

Le risposte precedenti si basavano sul raddoppio del testo e mancavano di spazi bianchi sufficienti.

Utilizzando atope &nbsp;sono stato in grado di ottenere i risultati che volevo.

Questo esempio include anche le frecce, un caso d'uso comune per le etichette di testo SVG:

<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>

-1

Puoi aggiungere uno stile al tuo testo:

  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;"

Bianco, in questo esempio. Non funziona in IE :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.