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?


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

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>


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!


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

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


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>


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> 


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.


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>

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.