Колір фону тексту у 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.