Warna latar belakang teks dalam SVG

101

Saya ingin mewarnai latar belakang svg textseperti background-colordi css

Saya hanya dapat menemukan dokumentasi fill, yang mewarnai teks itu sendiri

Apakah itu mungkin?

Nick Ginanto
sumber
Bisakah Anda membagikan kode Anda sejauh ini?
gotohales
stackoverflow.com/questions/12260370/… juga menunjukkan bagaimana melakukan ini dengan menggunakan filter.
Erik Dahlström
1
@RobertLongson Menutup pertanyaan ini sebagai duplikat ketika ditanyakan 2 tahun sebelumnya tampaknya salah, terutama ketika satu-satunya jawaban yang ada adalah milik Anda.
Balthazar
@ Aperçu: Usia pertanyaan bukanlah faktor utama saat memilih target duplikat, lihat misalnya di sini .
membunyikan klakson

Jawaban:

93

Tidak, ini tidak mungkin, elemen SVG tidak memiliki background-... atribut presentasi .

Untuk mensimulasikan efek ini Anda bisa menggambar persegi panjang di belakang atribut teks dengan fill="green"atau sesuatu yang serupa (filter). Menggunakan JavaScript, Anda dapat melakukan hal berikut:

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
sumber
8
Itu atau gunakan filter svg (feFlood + feComposite) pada teks. Lihat pertanyaan yang sedikit mirip stackoverflow.com/questions/12260370/… .
Erik Dahlström
3
Solusi yang menggunakan getBBox () ini, meskipun berfungsi dengan baik, bisa menjadi sangat lambat ketika banyak kalkulasi yang perlu dilakukan. Masalah dengan menggunakan filter svg (feFlood + feComposite) adalah teks yang keluar sedikit bergerigi. Telah menawarkan solusi sederhana, namun hacky di bawah ini.
dbarton_uk
Lebih baik menggunakan textElm = document.getElementById ("the-text") daripada textElm = ctx.getElementById ("the-text")?
Simon Hai
Bagaimana kal saya menggunakan fungsi getBBox yang sama di nodeJS
Ali
77

Anda bisa menggunakan filter untuk menghasilkan latar belakang.

<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
sumber
1
Apa artinya "SourceGraphic" di sini? Apakah "url (#solid)" sebenarnya menyebabkan akses web tambahan?
Ben Slade
7
teks buram di sini :(
teran
5
Bisakah Anda memberikan padding latar belakang ?
vsync
2
Suka solusi ini secara teori, tetapi dapat memastikan bahwa teksnya kabur. Sepertinya filter tersebut merusak anti-aliasing.
paulmelnikow
2
Tambahkan operator="xor"ke feCompositeuntuk mencegah teks buram. @RobertLongson @teran @paulmelnikow @bill
Saeid Zebardast
20

Solusi yang saya gunakan adalah:

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

Item teks duplikat sedang ditempatkan, dengan atribut stroke dan stroke-width. Stroke harus sesuai dengan warna latar belakang, dan lebar guratan harus cukup besar untuk membuat "percikan" untuk menulis teks yang sebenarnya.

Sedikit peretasan dan ada potensi masalah, tetapi berhasil untuk saya!

dbarton_uk
sumber
1
Saya menemukan solusi ini yang paling mudah.
Morgan Wilde
Dikonfirmasi ini sebagai solusi termudah
scipper
Juga mencetak dengan baik karena larutan filter sangat buram saat dicetak.
David Hunt
17

Tidak, Anda tidak dapat menambahkan warna latar belakang ke elemen SVG. Anda dapat melakukannya secara terprogram dengan 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
sumber
3
Ini tidak bekerja; itu hanya mengubah warna teks, bukan warna latar belakang.
David J.
Lampirkan teks dalam div atau span dan terapkan gaya ke salah satu dari dua yang terakhir Anda gunakan.
Arif Burhan
Posting ini menjelaskannya dengan baik: cambridge-intelligence.com/…
tukar
4

Jawaban oleh Robert Longson (@RobertLongson) dengan modifikasi:

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

dan kami tidak memiliki bluring dan tidak ada "getBBox" yang berat :) Padding disediakan oleh spasi putih dalam elemen teks dengan filter. Ini berhasil untuk saya

Roman Belov
sumber
2

ini adalah peretasan favorit saya (tidak yakin itu akan berhasil). Ini merujuk pada elemen yang belum ditampilkan, dan berfungsi dengan baik

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

Anda dapat menggabungkan filter dengan teks.

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

Bagi mereka yang bertanya-tanya bagaimana cara menerapkan padding ke elemen teks ketika memiliki latar belakang seperti pada jawaban Robert , lakukan hal berikut:

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

Dalam contoh di atas, posisi x dan y filter dapat digunakan sebagaimana transform: translate(-10%, -10%)mestinya, dan nilai lebar dan tinggi dapat dibaca sebagai 120%dan 120%. Jadi kami membuat latar belakang 20% ​​lebih besar, dan mengimbangi -10%, jadi latar belakang sekarang 10% lebih besar di setiap sisi teks.

momciloo
sumber
0

Jawaban sebelumnya mengandalkan penggandaan teks dan kekurangan spasi kosong.

Dengan menggunakan atopdan &nbsp;saya bisa mendapatkan hasil yang saya inginkan.

Contoh ini juga menyertakan panah, kasus penggunaan umum untuk label teks 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>
Kucing Henry
sumber
-1

Anda dapat menambahkan gaya ke teks Anda:

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

Putih, dalam contoh ini. Tidak bekerja di IE :)

Jan Pi
sumber