Color de fondo del texto en SVG


101

Quiero colorear el fondo de svg de manera textsimilar a background-coloren css

Solo pude encontrar documentación sobre fill, que colorea el texto en sí

¿Es siquiera posible?


¿Puedes compartir tu código hasta ahora?
gotohales


stackoverflow.com/questions/12260370/… también muestra cómo hacer esto usando filtros.
Erik Dahlström

1
@RobertLongson Cerrar esta pregunta como duplicada cuando se hizo 2 años antes que la otra parece incorrecto, especialmente cuando la única respuesta es la suya.
Balthazar

@ Aperçu: La edad de una pregunta no es el factor principal a la hora de elegir un objetivo duplicado, consulte, por ejemplo, aquí .
bocinazo

Respuestas:


93

No, esto no es posible, los elementos SVG no tienen background-... atributos de presentación .

Para simular este efecto, puede dibujar un rectángulo detrás del atributo de texto con fill="green"o algo similar (filtros). Con JavaScript, puede hacer lo siguiente:

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
Eso o use un filtro svg (feFlood + feComposite) en el texto. Vea una pregunta ligeramente similar stackoverflow.com/questions/12260370/… .
Erik Dahlström

3
Esta solución que usa getBBox (), aunque funciona bien, puede ser bastante lenta cuando es necesario realizar una gran cantidad de cálculos. El problema con el uso de un filtro svg (feFlood + feComposite) es que el texto sale un poco irregular. He ofrecido una solución simple pero hacky a continuación.
dbarton_uk

¿Es mejor usar textElm = document.getElementById ("el-texto") en lugar de textElm = ctx.getElementById ("el-texto")?
Simon Hola

¿Cómo puedo usar la misma función getBBox en nodeJS?
Ali

77

Puede utilizar un filtro para generar el fondo.

<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
¿Qué significa "SourceGraphic" aquí? ¿"Url (#sólido)" genera realmente un acceso web adicional?
Ben Slade

7
el texto está borroso aquí :(
teran

5
¿Puedes darle relleno al fondo ?
vsync

2
Me encanta esta solución en teoría, pero puedo confirmar que el texto está borroso. Parece que el filtro rompe el suavizado.
Paulmelnikow

2
Agregue operator="xor"a feCompositepara evitar texto borroso. @RobertLongson @teran @paulmelnikow @bill
Saeid Zebardast

20

La solución que he usado es:

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

Se está colocando un elemento de texto duplicado, con los atributos de trazo y ancho de trazo. El trazo debe coincidir con el color de fondo y el ancho del trazo debe ser lo suficientemente grande para crear una "mancha" en la que escribir el texto real.

Un poco complicado y hay problemas potenciales, ¡pero funciona para mí!


1
Encontré que esta solución es la más fácil.
Morgan Wilde

Confirmó esto como la solución más fácil
scipper

También imprime muy bien donde la solución de filtro estaba muy borrosa cuando se imprimió.
David Hunt

17

No, no puede agregar color de fondo a los elementos SVG. Puedes hacerlo programáticamente con 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
Esto no funciona; solo cambia el color del texto, no el color de fondo.
David J.

Incluya el texto en un div o span y aplique estilo a cualquiera de los dos últimos que haya utilizado.
Arif Burhan

Esta publicación lo explica bien: cambridge-intelligence.com/…
intercambio el


4

Respuesta de Robert Longson (@RobertLongson) con modificaciones:

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

y no tenemos bluring ni "getBBox" pesado :) El relleno lo proporcionan los espacios en blanco en el elemento de texto con filtro. Ha funcionado para mi


2

este es mi truco favorito (no estoy seguro de que funcione). Hace referencia a un elemento que aún no se muestra y funciona bastante bien

<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

Puede combinar el filtro con el texto.

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

Para aquellos que se preguntan cómo aplicar relleno a un elemento de texto cuando tiene un fondo como en la respuesta de Robert , haga lo siguiente:

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

En el ejemplo anterior, de filtros de x y Y posiciones pueden ser utilizados como transform: translate(-10%, -10%)lo haría, y la anchura y altura valores pueden leerse como 120%y 120%. Así que hicimos el fondo un 20% más grande y lo compensamos un -10%, por lo que el fondo ahora es un 10% más grande en cada lado del texto.


0

Las respuestas anteriores se basaron en duplicar el texto y carecían de suficiente espacio en blanco.

Al usar atopy&nbsp; pude obtener los resultados que quería.

Este ejemplo también incluye flechas, un caso de uso común para etiquetas de texto 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

Puede agregar estilo a su texto:

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

Blanco, en este ejemplo. No funciona en IE :)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.