【问题标题】:Can a nested SVG be used as input for feTile in an SVG?嵌套的 SVG 可以用作 SVG 中 feTile 的输入吗?
【发布时间】:2023-02-10 23:27:49
【问题描述】:

我在 SVG 文件中结合使用 feTilefeOffset 来创建一个充满图案的阴影。图案本身也是一个 SVG 文件。为了保持完整的 SVG 独立,我想在其中嵌入模式而不是引用外部文件。

我发现的丑陋解决方法是对模式文件进行 base64 编码。此代码产生预期结果:

<svg>
    <defs>

        <!-- Base64-encoded below-->
        <!-- <svg id="pattern1" xmlns='http://www.w3.org/2000/svg' width='10' height='10'> -->
        <!--   <rect width='10' height='10' fill='#fff' /> -->
        <!--   <circle cx="1" cy="1" r="1" fill="#000"/> -->
        <!-- </svg> -->

        <filter id="dropshadow" height="130%">

            <!-- This does not work -->
            <!-- <feImage width="3" height="3" result="checkerboard-image" xlink:href="#pattern1" /> -->

            <feImage width="3" height="3" result="checkerboard-image"
            xlink:href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScxMCcgaGVpZ2h0PScxMCc+CiAgPHJlY3Qgd2lkdGg9JzEwJyBoZWlnaHQ9JzEwJyBmaWxsPScjZmZmJyAvPgogIDxjaXJjbGUgY3g9IjEiIGN5PSIxIiByPSIxIiBmaWxsPSIjMDAwIi8+Cjwvc3ZnPg==" />

            <feTile in="checkerboard-image" result="texture" />
            <feOffset dx="30" dy="20" result="offsetblur"/>
            <feMerge>
                <feMergeNode/> <!-- this contains the offset blurred image -->
                <feMergeNode in="SourceGraphic"/> <!-- this contains the element that the filter is applied to -->
            </feMerge>
        </filter>
    </defs>

    <rect fill=white stroke=black x="10" y="10" width="200" height="100" style="filter:url(#dropshadow)" />
</svg>

我尝试嵌套 pattern-SVG 并使用它的 ID 引用它(请参阅代码中的代码注释),但这并没有显示任何内容。

是否可以做这样的事情来为模式引用另一个 SVG?

<feImage width="3" height="3" result="checkerboard-image" xlink:href="#pattern1" />

编辑:我找到了一种方法,但它似乎只适用于 chrome/chromium,firefox 例如没有正确呈现它。此外,添加更多 rect 的过滤器仍然无法正常工作

<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" id="svg24" width="100%" height="1000" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<defs id="defs15">
    <g transform="scale(0.25)" id="dotted-pattern">
        <rect style="fill-opacity:0" id="pattern-box" width="16" height="16" />
        <circle style="fill:#000" id="pattern-circle1" cx="10" cy="10" r="2" />
        <circle style="fill:#000" id="pattern-circle2" cx="2" cy="2" r="2" />
    </g>
    <filter
       id="dropshadow"
       height="1.154449"
       x="-0.0044999999"
       y="-0.0049999999"
       width="1.0582259">

      <feImage width="4" height="4" result="pattern-image" href="#dotted-pattern" />
      <feTile in="pattern-image" result="texture" id="feTile4" />

      <feOffset dx="11" dy="15" result="offsetblur" id="feOffset6" />
      <feMerge id="feMerge12">
          <feMergeNode id="feMergeNode8" /> <feMergeNode in="SourceGraphic" id="feMergeNode10" />
      </feMerge>
    </filter>
  </defs>
  <rect fill="#ffffff" stroke="#000000" x="10" y="10" width="200" height="100" style="filter:url(#dropshadow)" id="node2" />
</svg>

【问题讨论】:

  • SVG 是 xml 格式,必须对二进制数据进行编码。 Base64 字符串是完成结果的一种方式。通常在具有多层图形的 SVG 中,层是文件的 URL。

标签: xml svg svg-filters


【解决方案1】:

要回答您的具体问题,根据 SVG 1.1 规范,是的。关于 feImage,https://www.w3.org/TR/SVG11/filters.html#feImageElement 指出

该滤镜基元可以引用外部图像,也可以是对另一片 SVG 的引用。

这个声明在 SVG 2 的规范中没有改变。

我尝试将您编辑的代码与 g 元素转换为 svg 元素,并且两者都在 Chrome 中呈现正常,但在 Firefox 中却没有。

一般与您的阴影相关的两个 cmets:

  1. 除了使用不同的图案外,原始版本在白色背景上制作了点阴影,而编辑版本的阴影背景是透明的,这可能不是您想要的。

  2. 除非要添加阴影的预期形状都是矩形,否则您还需要将阴影过滤为 SourceGraphic 的形状,因为 feTile 会平铺其整个原始子区域。所以即使是圆圈也会有矩形阴影。

【讨论】:

    猜你喜欢
    • 2011-09-02
    • 1970-01-01
    • 2011-12-23
    • 2011-07-23
    • 2011-09-26
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 2014-05-28
    相关资源
    最近更新 更多