【问题标题】:Background color of text in SVGSVG中文本的背景颜色
【发布时间】:2015-09-09 16:19:16
【问题描述】:

我想给 svg text 的背景上色,类似于 css 中的 background-color

我只能在 fill 上找到文档,它为文本本身着色

有可能吗?

【问题讨论】:

标签: css svg background-color


【解决方案1】:

不,这是不可能的,SVG 元素没有background-... presentation attributes

要模拟这种效果,您可以使用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);

【讨论】:

  • 在文本上使用 svg 过滤器(feFlood + feComposite)。见略有相似的问题stackoverflow.com/questions/12260370/…
  • 这个使用 getBBox() 的解决方案虽然工作得很好,但在需要进行大量计算时可能会很慢。使用 svg 过滤器(feFlood + feComposite)的问题是文本出现了一些锯齿状。在下面提供了一个简单但很老套的解决方案。
  • 最好使用 textElm = document.getElementById("the-text") 而不是 textElm = ctx.getElementById("the-text")?
  • 如何在 nodeJS 中使用相同的 getBBox 函数
【解决方案2】:

不,您不能为 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");

【讨论】:

  • 这不起作用;它只改变文本的颜色,而不是背景颜色。
  • text 括在 divspan 中,并将样式应用于您使用的最后两个中的任何一个。
  • 这篇文章解释得很好:cambridge-intelligence.com/…
【解决方案3】:

您可以使用过滤器来生成背景。

<svg width="100%" height="100%">
  <defs>
    <filter x="0" y="0" width="1" height="1" id="solid">
      <feFlood flood-color="yellow" result="bg" />
      <feMerge>
        <feMergeNode in="bg"/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>
  <text filter="url(#solid)" x="20" y="50" font-size="50">solid background</text>
</svg>

【讨论】:

  • 这里的“SourceGraphic”是什么意思? “url(#solid)”真的会导致额外的网络访问吗?
  • 这里的文字模糊 :(
  • 可以给背景padding吗?
  • 理论上喜欢这个解决方案,但可以确认文字模糊。过滤器似乎破坏了抗锯齿功能。
  • operator="xor" 添加到feComposite 以防止文本模糊。 @RobertLongson @teran @paulmelnikow @bill
【解决方案4】:

我使用的解决方案是:

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

正在放置一个重复的文本项,具有笔画和笔画宽度属性。笔画应与背景颜色相匹配,并且笔画宽度应刚好足以创建一个“splodge”,以便在其上书写实际文本。

有点破解,有潜在的问题,但对我有用!

【讨论】:

  • 我发现这个解决方案是最简单的。
  • 确认这是最简单的解决方案
  • 在打印时过滤器溶液非常模糊的地方也打印得很好。
  • 最佳解决方案!!
  • 太棒了! ! !
【解决方案5】:

Robert Longson (@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”:) 填充由带有过滤器的文本元素中的空格提供。 它对我有用

【讨论】:

    【解决方案6】:

    这是我最喜欢的 hack(不确定它是否可以工作)。它引用了一个尚未显示的元素,并且效果很好

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

    【讨论】:

      【解决方案7】:

      可以使用&lt;foreignObject&gt; 标记代替&lt;text&gt; 标签,它允许带有CSS 的XHTML 内容。

      【讨论】:

      【解决方案8】:

      您可以为文本添加样式:

        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 中不起作用 :)

      【讨论】:

        【解决方案9】:

        您可以将过滤器与文本结合使用。

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

        【讨论】:

          【解决方案10】:

          之前的答案依赖于将文本加倍并且缺少足够的空格。

          通过使用atop&amp;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>
          

          【讨论】:

          • 使用 &amp;nbsp; 而不是 &amp;#160; 在许多浏览器上会导致问题,因为它不能验证为 SVG。此外,您可能希望将 xmlns="http://www.w3.org/2000/svg" 作为属性添加到 svg 标记,以确保浏览器正确解释这一点(例如,这在 Firefox 上不起作用)。
          【解决方案11】:

          对于那些想知道如何在文本元素具有Robert's answer 中的背景时对其应用填充的人,请执行以下操作:

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

          在上面的例子中,过滤器的 xy 位置可以像 transform: translate(-10%, -10%) 那样使用,widthheight 值可以读作120%120%。所以我们将背景扩大了 20%,并将其抵消了 -10%,所以背景现在在文本的每一侧都扩大了 10%。

          【讨论】:

            猜你喜欢
            • 2021-06-03
            • 2021-12-04
            • 1970-01-01
            相关资源
            最近更新 更多