在应用滤镜之前抗锯齿SVG文本?

3

SVG滤镜会栅格化它们的源图像,这意味着被过滤的文本不会进行抗锯齿处理,从而导致边缘的锯齿状。

有没有解决方法?也许可以使用另一个过滤器来模拟抗锯齿效果,或者我可以在应用过滤器之前对文本进行抗锯齿处理?

相关滤镜:

<filter id="f">
  <feGaussianBlur in="SourceGraphic" stdDeviation="0" result="blur" />
  <feColorMatrix
    in="blur"
    mode="matrix"
    values="1 0 0 0 0
    0 1 0 0 0
    1 0 1 0 0
    0 0 0 15 -8"
    result="goo"
  />
  <feComposite in="SourceGraphic" in2="goo" operator="atop" />
</filter>

您的假设不正确。提供给过滤器作为输入的文本元素将在光栅化之前进行抗锯齿处理,而且该过滤器会保留抗锯齿效果,除非您对 Alpha 通道进行了某些操作。请提供一个最小可验证测试用例(即代码),说明您遇到的具体用例。 - Michael Mullany
https://codesandbox.io/s/hardcore-water-yny8u - 您会在顶部的 <text> 上看到锯齿状边缘。 在低PPI屏幕上更加明显。 - aleclarson
2个回答

1

有没有绕过这个问题的方法?也许可以使用另一个过滤器来模拟抗锯齿,或者我可以在过滤器应用之前以某种方式对文本进行抗锯齿处理?

这个 答案 对这个问题进行了详细解释。

作为妥协的解决方案,您可以尝试:

  1. 选择颜色对比度较小的字母和背景颜色
  2. 将属性shape-rendering =" crispEdges"应用于字体
  3. 选择呈现更清晰边缘的字体

例如,您选择的字体font-family =" cursive "如下所示:

enter image description here

<svg version="1.1" xmlns="http://www.w3.org/2000/svg"     xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="600" viewBox="0 0 400 400" >  

<text  x="35" y="150" font-size="100px" fill="black" font-family="cursive"> HELLO </text>

</svg>

font-family = "Monotype Corsiva" 看起来更好

enter image description here

<svg version="1.1" xmlns="http://www.w3.org/2000/svg"     xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="200" viewBox="0 0 400 200" >  

<rect width="100%" height="100%" fill="silver" />
<text  x="35" y="120" font-size="100px" fill="#444444" shape-rendering="crispEdges" font-family="Monotype Corsiva"  > HELLO </text>

</svg>  

应用SVG滤镜以平滑锯齿状边缘

  • 对于feGaussianBlur滤镜,选择参数(矩阵的最后一行)0 0 0 29 -1
  • 对于feComposite滤镜,operator="atop"

<svg version="1.1" xmlns="http://www.w3.org/2000/svg"     xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="200" viewBox="0 0 400 200" >  
<defs>
  <filter id="f">
  <feGaussianBlur in="SourceGraphic" stdDeviation="1" result="blur" >
        
    </feGaussianBlur>   
            <feColorMatrix in="blur" type="matrix"
                values="
                  1 0 0 0 0
                  0 1 0 0 0
                  0 0 1 0 0
                  0 0 0 29 -1"
                  result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
        </filter>
</defs> 
<rect width="100%" height="100%" fill="silver" />
<text filter="url(#f)"  x="35" y="120" font-size="100px" fill="#444444" shape-rendering="crispEdges" font-family="Monotype Corsiva"  > HELLO </text>

</svg>  

筛选器动画

我正在对feGaussianBlur的stdDeviation进行动画处理。

根据@aleclarson的评论,您希望对筛选器属性进行动画处理。

<animate attributeName="stdDeviation" begin="0s" dur="8s"
  repeatCount="indefinite" values="1;6;12;12;6;1;1" />

<svg version="1.1" xmlns="http://www.w3.org/2000/svg"     xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="200" viewBox="0 0 400 200" >  
<defs>
  <filter id="f">
  <feGaussianBlur in="SourceGraphic" stdDeviation="1" result="blur" >
   <animate attributeName="stdDeviation" begin="0s" dur="8s" repeatCount="indefinite" values="1;6;12;12;6;1;1" />
    </feGaussianBlur>       
            <feColorMatrix in="blur" type="matrix"
                values="
                  1 0 0 0 0
                  0 1 0 0 0
                  0 0 1 0 0
                  0 0 0 29 -1"
                  result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
        </filter>
</defs> 

<text filter="url(#f)"  x="35" y="120" font-size="100px" fill="#111111" shape-rendering="crispEdges" font-family="Monotype Corsiva"  > HELLO </text>

</svg>  

变量带有值和运算符 = "xor"

<svg version="1.1" xmlns="http://www.w3.org/2000/svg"     xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="200" viewBox="0 0 400 200" >  
<defs>
  <filter id="f">
  <feGaussianBlur in="SourceGraphic" stdDeviation="1" result="blur" >
   <animate attributeName="stdDeviation" begin="0s" dur="8s" repeatCount="indefinite" values="1;6;12;12;6;1;1" />
    </feGaussianBlur>       
            <feColorMatrix in="blur" type="matrix"
                values="
                  1 0 0 0 0
                  0 1 0 0 0
                  0 0 1 0 0
                  0 0 0 29 -1"
                  result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="xor"/>
        </filter>
</defs> 

<text filter="url(#f)"  x="35" y="120" font-size="100px" fill="#111111" shape-rendering="crispEdges" font-family="Monotype Corsiva"  > HELLO </text>

</svg>  


1

输入到滤镜中的文本元素在光栅化之前会进行抗锯齿处理,并且该滤镜保留了抗锯齿效果,除非您对 alpha 通道进行了一些操作。

在这种情况下,您正在对 alpha 通道进行一些操作。那个 feColorMatrix 滤镜将 alpha 通道乘以 15,然后减去 8。这会导致将不透明度小于 8/15 的像素转换为透明 - 这会削弱大部分抗锯齿效果。

如果您想稍微平滑边缘,可以添加另一个带有 0.5 或 1 单位 stdDeviation 的 feGaussianBlur 到末尾。还有其他方法可以添加回抗锯齿效果,但这实际上取决于您要做什么。由于当前的滤镜没有任何作用 - 我假设意图是为了动画一些东西?

(另外 - 那个 feColorMatrix 应该有 type='matrix' 而不是 mode='matrix' - mode 只用于 feBlend。)

更新:不妨添加一些平滑边缘的技巧。

  1. 原始
  2. 带脆皮滤镜的原始版本
  3. #2加上一个小模糊标签在结尾处
  4. #2加上一个小模糊标签,但被剪裁到一个像素的边界
  5. #2加上一个小模糊,但低透明度部分的模糊被剪裁为零

<svg width="1000px" height="1000px" >
  <filter id="f1">
  <feGaussianBlur in="SourceGraphic" stdDeviation="0" result="blur" />
  <feColorMatrix
    in="blur"
    mode="matrix"
    values="1 0 0 0 0
    0 1 0 0 0
    1 0 1 0 0
    0 0 0 15 -8"
    result="goo"
  />
  <feComposite in="SourceGraphic" in2="goo" operator="atop" />
</filter>
  
<filter id="f2">
  <feGaussianBlur in="SourceGraphic" stdDeviation="0" result="blur" />
  <feColorMatrix
    in="blur"
    mode="matrix"
    values="1 0 0 0 0
    0 1 0 0 0
    1 0 1 0 0
    0 0 0 15 -8"
    result="goo"
  />
  <feComposite in="SourceGraphic" in2="goo" operator="atop" />
    <feGaussianBlur stdDeviation="1"/>
</filter>
  
  <filter id="f3">
  <feGaussianBlur in="SourceGraphic" stdDeviation="0" result="blur" />
  <feColorMatrix
    in="blur"
    mode="matrix"
    values="1 0 0 0 0
    0 1 0 0 0
    1 0 1 0 0
    0 0 0 15 -8"
    result="goo"
  />
  <feComposite in="SourceGraphic" in2="goo" operator="atop" result="pre-final"/>
  <feMorphology operator="dilate" radius="1" result="base"/>
   <feGaussianBlur in="pre-final" stdDeviation="1" />
  <feComposite in2="base" operator="in" />
</filter>
  
  
<filter id="f4">
  <feGaussianBlur in="SourceGraphic" stdDeviation="0" result="blur" />
  <feColorMatrix
    in="blur"
    mode="matrix"
    values="1 0 0 0 0
    0 1 0 0 0
    1 0 1 0 0
    0 0 0 15 -8"
    result="goo"
  />
  <feComposite in="SourceGraphic" in2="goo" operator="atop" result="pre-final"/>
  <feGaussianBlur stdDeviation="1"/>
  <feComponentTransfer>
    <feFuncA type="table" tableValues="0 0 .7 .8 .9 1"/>
  </feComponentTransfer>
</filter>
  
  
  <text x="50" y="150" style="font-size: 160; font-weight: bold;">FILTERED </text>
    <text filter="url(#f1)" x="50" y="300" style="font-size: 160; font-weight: bold;">FILTERED </text>
      <text filter="url(#f2)" x="50" y="450" style="font-size: 160; font-weight: bold;">FILTERED </text>
        <text filter="url(#f3)" x="50" y="600" style="font-size: 160; font-weight: bold;">FILTERED </text>
         <text filter="url(#f4)" x="50" y="750" style="font-size: 160; font-weight: bold;">FILTERED </text> 

  </svg>


我正在对feGaussianBlurstdDeviation进行动画处理。感谢您的建议,我很快会尝试! - aleclarson
@Michael Mullany非常感谢您提供的理论部分答案。请求您提供实际示例,以展示这些滤波器的效果。 - Alexandr_TT
以下是您可以做的一些示例:https://codepen.io/mullany/pen/1e5c1223cad2a0ad07cd0c5d31e141f0 - Michael Mullany
@MichaelMullany 非常感谢您提供的示例。 - Alexandr_TT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接