Цвет фона текста в SVG

101

Я хочу раскрасить фон svg так textже, как background-colorв css

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

Это вообще возможно?

Ник Гинанто
источник
Можете ли вы пока поделиться своим кодом?
gotohales
stackoverflow.com/questions/12260370/… также показывает, как это сделать с помощью фильтров.
Erik Dahlström
1
@RobertLongson Закрытие этого вопроса как дубликата, когда он был задан за 2 года до другого, кажется неправильным, особенно когда единственный ответ - ваш.
Balthazar
@ 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/… .
Erik Dahlström
3
Это решение, использующее getBBox (), хотя и работает нормально, может быть довольно медленным, когда необходимо выполнить большое количество вычислений. Проблема с использованием svg-фильтра (feFlood + feComposite) заключается в том, что текст выходит немного неровным. Ниже предложили простое, но хакерское решение.
dbarton_uk
Лучше использовать textElm = document.getElementById ("the-text") вместо textElm = ctx.getElementById ("the-text")?
Саймон Хай
Как я использую ту же функцию getBBox в nodeJS
Али
78

Вы можете использовать фильтр для создания фона.

<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
текст здесь расплывчатый :(
Teran 06
5
Можете ли вы дать фоновое заполнение ?
vsync
2
Люблю это решение в теории, но могу подтвердить, что текст размытый. Похоже фильтр сглаживание ломает.
Полмельников
2
Добавить operator="xor"в feCompositeпредотвратить расплывчатый текст. @RobertLongson @teran @paulmelnikow @bill
Саид Зебардаст
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>

Размещается повторяющийся текстовый элемент с атрибутами обводки и ширины обводки. Обводка должна соответствовать цвету фона, а ширина обводки должна быть достаточно большой, чтобы создать «пятно», на котором можно написать фактический текст.

Немного взлома и есть потенциальные проблемы, но у меня работает!

dbarton_uk
источник
1
Я нашел это решение самым простым.
Морган Уайлд
Подтвердил, что это самое простое решение
scipper
Также хорошо печатается там, где раствор фильтра был очень размытым при печати.
Дэвид Хант
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
Это не работает; он изменяет только цвет текста, но не цвет фона.
Дэвид Дж.
1
Заключите текст в div или span и примените стиль к любому из последних двух, которые вы использовали.
Ариф Бурхан,
Этот пост хорошо это объясняет: cambridge-intelligence.com/…
exchange
6

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

Крис Дж.
источник
1
Вы можете оставить пример?
IgniteCoders
1
Недооцененный ответ. 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>

Калимеро100582
источник
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% больше с каждой стороны текста.

Momciloo
источник
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 :)

Ян Пи
источник