Колір фону тексту у SVG


101

Я хочу забарвити фон svg, textподібний до background-colorcss

Мені вдалося знайти лише документацію щодо того fill, який колір самого тексту

Чи можливо це навіть?


Чи можете ви поділитися своїм кодом поки?
gotohales


stackoverflow.com/questions/12260370/… також показує, як це зробити за допомогою фільтрів.
Ерік Далстрем

1
@RobertLongson Закриття цього питання як дублікату, коли воно було задане за 2 роки до іншого, здається неправильним, особливо коли єдина відповідь там - ваша.
Бальтазар

@ Aperçu: Вік питання не є головним фактором при виборі повторюваної цілі, див. Приклад тут .
приворот

Відповіді:


93

Ні, це неможливо, елементи SVG не мають background-... атрибутів презентації .

Щоб імітувати цей ефект, ви можете намалювати прямокутник за текстовим атрибутом із fill="green"чимось подібним (фільтри). За допомогою JavaScript ви можете зробити наступне:

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
Для цього використовуйте svg фільтр (feFlood + feComposite) у тексті. Дивіться трохи схоже запитання stackoverflow.com/questions/12260370/… .
Ерік Далстрем

3
Це рішення з використанням getBBox (), хоча воно і працює дуже добре, може бути досить повільним, коли потрібно зробити велику кількість обчислень. Проблема використання фільтра svg (feFlood + feComposite) полягає в тому, що текст виходить трохи нерівним. Нижче ми запропонували просте, але шалене рішення.
dbarton_uk

Краще використовувати textElm = document.getElementById ("текст") замість textElm = ctx.getElementById ("текст")?
Саймон Хай

Як я використовую ту саму функцію getBBox у nodeJS
Алі,

77

Ви можете використовувати фільтр для створення фону.

<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
Що тут означає "SourceGraphic"? Чи "url (#solid)" насправді викликає додатковий доступ до Інтернету?
Бен Слейд

7
текст тут розмитий :(
теран

5
Чи можете ви дати фонову підкладку ?
vsync

2
Теоретично люблю це рішення, але може підтвердити, що текст розмитий. Здається, фільтр розбиває згладжування.
paulmelnikow

2
Додайте operator="xor"до, feCompositeщоб запобігти розмитості тексту. @RobertLongson @teran @paulmelnikow @bill
Saeid Zebardast

20

Рішення, яке я використовував:

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

Розміщується дублікат текстового елемента з атрибутами обведення та ширини обведення. Штрих повинен відповідати кольорові фону, а ширина штриху повинна бути достатньо великою, щоб створити «шлейф», на якому написати фактичний текст.

Трохи хак і є потенційні проблеми, але працює для мене!


1
Я знайшов це рішення найпростішим.
Morgan Wilde

Підтвердив це як найпростіший варіант рішення
науковець

Також добре друкується там, де фільтр був дуже розмитим при друкуванні.
Девід Хант,

17

Ні, ви не можете додати колір фону до елементів SVG. Ви можете зробити це програмно за допомогою 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
Це не працює; він змінює лише колір тексту, а не колір фону.
Девід Дж.

Вкладіть текст у div або span і застосуйте стиль до будь-якого з останніх двох, які ви використовували.
Аріф Бурхан

Ця публікація це добре пояснює: cambridge-intelligence.com/…
обмін

5

Замість того, щоб використовувати <text>тег, <foreignObject>можна використовувати тег, який дозволяє вміст XHTML за допомогою CSS.


1
Чи можете ви залишити приклад?
IgniteCoders

Занижена відповідь. developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject Містить корисний приклад. У вашому ForeignObject ви можете використовувати divs & span, а також визначення CSS.
доктор Джеррі,

4

Відповідь Роберта Лонгсона (@RobertLongson) зі змінами:

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

і ми не маємо розмитості і важкого "getBBox" :) Відступ забезпечується пробілами в текстовому елементі з фільтром. Це спрацювало для мене


2

це мій улюблений хак (не впевнений, що він повинен працювати). Він посилається на елемент, який ще не відображається, і він працює досить добре

<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

Ви можете комбінувати фільтр з текстом.

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

Для тих, хто цікавиться, як застосувати відступ до текстового елемента, коли він має тло, як у відповіді Роберта , зробіть наступне:

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

У наведеному вище прикладі позиції фільтра x та y можна використовувати як transform: translate(-10%, -10%)би, а значення ширини та висоти можна прочитати як 120%і 120%. Отже, ми зробили фон на 20% більшим, а компенсували його на -10%, тож фон тепер на 10% більше з кожного боку тексту.


0

Попередні відповіді спирались на подвоєння тексту та не мали достатнього пробілу.

Використовуючи, atopі &nbsp;я зміг отримати бажані результати.

Цей приклад також включає стрілки, типовий варіант використання текстових міток 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

Ви можете додати стиль тексту:

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

Білий, у цьому прикладі. Не працює в IE :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.