【问题标题】:How to create a blurred label background with SVG filters?如何使用 SVG 滤镜创建模糊的标签背景?
【发布时间】:2019-11-12 05:32:44
【问题描述】:

我想对以下问题有一个好的工作方法:

在条形图上用不同但未知的颜色填充条形图,我想用固定的黑色放置标签,以便它们可读。

我正在搜索的方法应该类似于图像中窗口的标题栏中。标签是黑色的,它位于模糊的白色背景之上,该背景位于任何颜色的条的顶部。

有没有办法用 SVG 过滤器做到这一点?

以下是我尝试过的一些方法:

    .black {
      fill: black;
    }
    .blue {
      fill: blue;
    }
    .red {
      fill: red;
    }    
    .yellow {
      fill: yellow;
    }
    .label{
      fill: black;
      font-size: 14px;
    }
    .label-background{
      fill: white;
      font-size: 16px;
    }
    .text-background{
      paint-order: stroke;
      stroke: #fff;
      fill: black;
      stroke-width: 5px;
    }
    .header{
      font-size: 20px;
    }
    .background{
      fill: white;
      opacity: 0.6;
    }
  <svg width="500" height="500">
    <defs>
      <filter x="-0.05" y="-0.1" width="1.08" height="1.2" id="solid">
        <feFlood flood-color="lightgrey"/>
        <feComposite in="SourceGraphic" operator="xor" />
      </filter>
    </defs>

    <g class="row-1" transform="translate(0,30)">
      <text class="header" x="20" y="-10">text label on top of bar </text>
      <g>
        <rect class="black" width=100 height=30></rect>
        <text class="label" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(120,0)">
        <rect class="blue" width=100 height=30></rect>
        <text class="label" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(240,0)">
        <rect class="red" width=100 height=30></rect>
        <text class="label" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(360,0)">
        <rect class="yellow" width=100 height=30></rect>
        <text class="label" x="20" y="20">my text label</text>
      </g>
    </g>  
    
		<g class="row-2" transform="translate(0,100)">
      <text class="header" x="20" y="-10">text label on top of rect.background on top of bar </text>
      <g>
        <rect class="black" width=100 height=30></rect>
        <rect class="background" x=17 y=6 width=78 height=19></rect>
        <text class="label" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(120,0)">
        <rect class="blue" width=100 height=30></rect>
        <rect class="background" x=17 y=6 width=78 height=19></rect>
        <text class="label" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(240,0)">
        <rect class="red" width=100 height=30></rect>
        <rect class="background" x=17 y=6 width=78 height=19></rect>
        <text class="label" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(360,0)">
        <rect class="yellow" width=100 height=30></rect>
        <rect class="background" x=17 y=6 width=78 height=19></rect>
        <text class="label" x="20" y="20">my text label</text>
      </g>
  	</g>
    
    <g class="row-3" transform="translate(0, 170)">
      <text class="header" x="20" y="-10">text label with filter #solid on top of bar </text>
      <g>
        <rect class="black" width=100 height=30></rect>
        <text class="label" filter="url(#solid)" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(120,0)">
        <rect class="blue" width=100 height=30></rect>
        <text class="label" filter="url(#solid)" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(240,0)">
        <rect class="red" width=100 height=30></rect>
        <text class="label" filter="url(#solid)" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(360,0)">
        <rect class="yellow" width=100 height=30></rect>
        <text class="label" filter="url(#solid)" x="20" y="20">my text label</text>
      </g>
    </g> 

    <g class="row-4" transform="translate(0, 240)">
      <text class="header" x="20" y="-10">text label on top of larger text label with background color on top of bar </text>
      <g>
        <rect class="black" width=100 height=30></rect>
        <text class="label-background" x="18" y="22">my text label</text>
        <text class="label" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(120,0)">
        <rect class="blue" width=100 height=30></rect>
        <text class="label-background" x="18" y="22">my text label</text>
        <text class="label" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(240,0)">
        <rect class="red" width=100 height=30></rect>
        <text class="label-background" x="18" y="22">my text label</text>
        <text class="label" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(360,0)">
        <rect class="yellow" width=100 height=30></rect>
        <text class="label-background" x="18" y="22">my text label</text>
        <text class="label" x="20" y="20">my text label</text>
      </g>
    </g> 
    
    <g class="row-5" transform="translate(0, 310)">
      <text class="header" x="20" y="-10">text label with paint-order: stroke on top of bar </text>
      <g>
        <rect class="black" width=100 height=30></rect>
        <text class="label text-background" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(120,0)">
        <rect class="blue" width=100 height=30></rect>
        <text class="label text-background" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(240,0)">
        <rect class="red" width=100 height=30></rect>
        <text class="label text-background" x="20" y="20">my text label</text>
      </g>

      <g transform="translate(360,0)">
        <rect class="yellow" width=100 height=30></rect>
        <text class="label text-background" x="20" y="20">my text label</text>
      </g>
    </g> 
  </svg>
  

【问题讨论】:

    标签: css svg svg-filters


    【解决方案1】:

    既然您要的是 SVG 过滤器解决方案:

    1. SourceAlpha 开始,它会为您提供元素(即文本)的黑色轮廓,然后使用 feGaussianBlur 对其进行模糊以创建柔和的阴影。
    2. 这个阴影是黑色的,所以用feColorMatrix 把它变成白色。
    3. 最后,使用feBlend将原始文本放在阴影上。

    参考资料:

    .black {
      fill: black;
    }
    .blue {
      fill: blue;
    }
    .red {
      fill: red;
    }    
    .yellow {
      fill: yellow;
    }
    .label {
      fill: black;
      font-size: 14px;
    }
    <svg width="500" height="80" color-interpolation-filters="sRGB">
      <defs>
        <filter id="shadow">
          <feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur" />
          <feColorMatrix in="blur" type="matrix" values="0  0  0  0  1
                                                         0  0  0  0  1
                                                         0  0  0  0  1
                                                         0  0  0  8  0" result="white" />
          <feColorMatrix in="white" type="matrix" values="1  0  0  0  0
                                                          0  1  0  0  0
                                                          0  0  1  0  0
                                                          0  0  0 .8  0" result="dim" />
          <feBlend in="SourceGraphic" in2="dim" mode="normal" />
        </filter>
      </defs>
    
      <g class="row-1" transform="translate(10,30)">
        <text class="header" x="0" y="-10">feGaussianBlur on SourceAlpha</text>
        <g>
          <rect class="black" width=100 height=30></rect>
          <text class="label" x="20" y="20" filter="url(#shadow)">my text label</text>
        </g>
        <g transform="translate(120,0)">
          <rect class="blue" width=100 height=30></rect>
          <text class="label" x="20" y="20" filter="url(#shadow)">my text label</text>
        </g>
        <g transform="translate(240,0)">
          <rect class="red" width=100 height=30></rect>
          <text class="label" x="20" y="20" filter="url(#shadow)">my text label</text>
        </g>
        <g transform="translate(360,0)">
          <rect class="yellow" width=100 height=30></rect>
          <text class="label" x="20" y="20" filter="url(#shadow)">my text label</text>
        </g>
      </g>  
    </svg>

    【讨论】:

    • 非常感谢!一个问题:为什么带有标签的黄色条比使用普通文本更难阅读?过滤器是否也会使字体更加模糊?
    • 我可以看到它有点不同,因为过滤器,但我不知道为什么会这样。从小测试来看,feColorMatrix 似乎改变了最终结果。
    • 也许就像在对 Robert Longsons 的评论中对 stackoverflow.com/questions/15500894/… 的回答中解释的那样,我们最后需要一个 feComposite operator=xor
    • 看起来xor 只是在白色阴影中切了一个文字形状的洞?然而,在玩了yoksel's SVG Filters Playground 之后,当我将color-interpolation-filters 设置为sRGB 时,情况看起来好多了。看看我更新的答案是否适合你。
    【解决方案2】:

    未经过彻底测试,但使用多个值构建 text-shadow 具有预期的效果:

        svg text {
          text-shadow: 0px 0px 2px white,
                       0px 0px 4px white,
                       0px 0px 6px white,
                       0px 0px 8px white,
                       0px 0px 10px white;
        }
    

    工作示例:

        .black {
          fill: black;
        }
        .blue {
          fill: blue;
        }
        .red {
          fill: red;
        }    
        .yellow {
          fill: yellow;
        }
        .label{
          fill: black;
          font-size: 14px;
        }
    
    svg g.row-1 text {
      text-shadow: 0px 0px 2px white,
                   0px 0px 4px white,
                   0px 0px 6px white,
                   0px 0px 8px white,
                   0px 0px 10px white;
    }
    <svg width="500" height="500">
        <defs>
          <filter x="-0.05" y="-0.1" width="1.08" height="1.2" id="solid">
            <feFlood flood-color="lightgrey"/>
            <feComposite in="SourceGraphic" operator="xor" />
          </filter>
        </defs>
    
        <g class="row-1" transform="translate(0,30)">
          <g>
            <rect class="black" width=100 height=30></rect>
            <text class="label" x="20" y="20">my text label</text>
          </g>
    
          <g transform="translate(120,0)">
            <rect class="blue" width=100 height=30></rect>
            <text class="label" x="20" y="20">my text label</text>
          </g>
    
          <g transform="translate(240,0)">
            <rect class="red" width=100 height=30></rect>
            <text class="label" x="20" y="20">my text label</text>
          </g>
    
          <g transform="translate(360,0)">
            <rect class="yellow" width=100 height=30></rect>
            <text class="label" x="20" y="20">my text label</text>
          </g>
        </g>  
    </svg>
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-04
      • 2021-03-08
      • 2021-09-04
      • 1970-01-01
      • 2020-12-11
      • 2021-04-08
      • 2014-07-13
      • 2014-08-16
      相关资源
      最近更新 更多