Kolor tła tekstu w formacie SVG

101

Chcę pokolorować tło svg textpodobnie jak background-colorw css

Udało mi się tylko znaleźć dokumentację fill, która koloruje sam tekst

Czy to w ogóle możliwe?

Nick Ginanto
źródło
Czy możesz udostępnić swój kod do tej pory?
gotohales
stackoverflow.com/questions/12260370/… również pokazuje, jak to zrobić za pomocą filtrów.
Erik Dahlström
1
@RobertLongson Zamknięcie tego pytania jako duplikatu, gdy zostało zadane 2 lata wcześniej, wydaje się błędne, zwłaszcza gdy jedyna odpowiedź jest twoja.
Balthazar
@ Aperçu: Wiek pytania nie jest głównym czynnikiem przy wyborze podwójnego celu, patrz na przykład tutaj .
trąbka

Odpowiedzi:

93

Nie, nie jest to możliwe, elementy SVG nie mają background-... atrybutów prezentacji .

Aby zasymulować ten efekt, możesz narysować prostokąt za atrybutem tekstu za pomocą fill="green"lub czegoś podobnego (filtry). Używając JavaScript, możesz wykonać następujące czynności:

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
źródło
8
To lub użyj filtru SVG (feFlood + feComposite) w tekście. Zobacz nieco podobne pytanie stackoverflow.com/questions/12260370/… .
Erik Dahlström
3
To rozwiązanie wykorzystujące getBBox (), chociaż działa dobrze, może być dość powolne, gdy trzeba wykonać dużą liczbę obliczeń. Problem z używaniem filtra SVG (feFlood + feComposite) polega na tym, że tekst jest nieco poszarpany. Zaproponowałem poniżej proste, ale hackerskie rozwiązanie.
dbarton_uk
Lepiej użyć textElm = document.getElementById ("the-text") zamiast textElm = ctx.getElementById ("the-text")?
Simon Hi,
Jak cal używam tej samej funkcji getBBox w nodeJS
Ali
78

Możesz użyć filtra do wygenerowania tła.

<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
źródło
1
Co oznacza tutaj „SourceGraphic”? Czy „url (#solid)” faktycznie powoduje dodatkowy dostęp do sieci?
Ben Slade,
7
tekst jest zamazany tutaj :(
teran
5
Czy możesz podać wypełnienie tła ?
vsync,
2
Uwielbiam to rozwiązanie w teorii, ale mogę potwierdzić, że tekst jest rozmyty. Wygląda na to, że filtr przerywa antyaliasing.
paulmelnikow
2
Dodaj operator="xor"do, feCompositeaby zapobiec rozmyciu tekstu. @RobertLongson @teran @paulmelnikow @bill
Saeid Zebardast
20

Rozwiązanie, które zastosowałem to:

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

Umieszczany jest zduplikowany element tekstowy z atrybutami obrysu i szerokości obrysu. Obrys powinien pasować do koloru tła, a jego szerokość powinna być na tyle duża, aby utworzyć „rozdzielenie”, na którym można zapisać rzeczywisty tekst.

Trochę hack i są potencjalne problemy, ale dla mnie działa!

dbarton_uk
źródło
1
Uważam, że to rozwiązanie jest najłatwiejsze.
Morgan Wilde
Potwierdził to jako najłatwiejsze rozwiązanie
scipper
Ładnie drukuje również tam, gdzie roztwór filtrujący był bardzo rozmyty podczas drukowania.
David Hunt
17

Nie, nie możesz dodać koloru tła do elementów SVG. Możesz to zrobić programowo za pomocą 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");
nnattawat
źródło
3
To nie działa; zmienia tylko kolor tekstu, a nie kolor tła.
David J.,
1
Umieść tekst w elemencie div lub span i zastosuj styl do dowolnego z dwóch ostatnio używanych.
Arif Burhan
Ten post dobrze to wyjaśnia: cambridge-intelligence.com/…
wymiana
4

Odpowiedź Roberta Longsona (@RobertLongson) z modyfikacjami:

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

i nie mamy blasku ani ciężkiego "getBBox" :) Wypełnienie zapewniają białe spacje w elemencie tekstowym z filtrem. U mnie to zadziałało

Roman Belov
źródło
2

to mój ulubiony hack (nie jestem pewien, czy powinien działać). Odnosi się do elementu, który nie został jeszcze wyświetlony i działa całkiem nieźle

<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
źródło
2

Możesz połączyć filtr z tekstem.

<!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
źródło
1

Dla tych, którzy zastanawiają się, jak zastosować dopełnienie do elementu tekstowego, który ma tło, takie jak w odpowiedzi Roberta , wykonaj następujące czynności:

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

W powyższym przykładzie pozycje x i y filtru mogą być używane bez transform: translate(-10%, -10%)zmian, a wartości szerokości i wysokości można odczytywać jako 120%i 120%. Więc zwiększyliśmy tło o 20% i przesunęliśmy je o 10%, więc tło jest teraz o 10% większe z każdej strony tekstu.

momciloo
źródło
0

Poprzednie odpowiedzi opierały się na podwajaniu tekstu i nie zawierały wystarczającej ilości białych znaków.

Używając atopi &nbsp;byłem w stanie uzyskać pożądane rezultaty.

Ten przykład obejmuje również strzałki, typowy przypadek użycia etykiet tekstowych 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>
Kot Henry'ego
źródło
-1

Możesz dodać styl do swojego tekstu:

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

W tym przykładzie biały. Nie działa w IE :)

Jan Pi
źródło