SVG将颜色与整个背景混合

时间:2018-12-07 16:43:20

标签: svg svg-filters

我敢肯定这确实很简单,但是我正在制作SVG,其中我对每种CMYK颜色有4个<g>组,并且我将这4种颜色彼此合成。

我想为每一层使用多种颜色混合模式;每层都是CMYK各自的纯色,我希望将这些颜色混合以生成最终图像。

我使用CSS:

<svg //put svg intro tag stuff here>
<rect width="100%" height="100%" fill="white"/>
<g fill="#0FF" style="mix-blend-mode: multiply">
<!--shape primitives that go on the cyan layer-->
</g>
<g fill="#F0F" style="mix-blend-mode: multiply">
<!--shape primitives that go on the magenta layer-->
</g>
<g fill="#FF0" style="mix-blend-mode: multiply">
<!--shape primitives that go on the yellow layer-->
</g>
<g fill="#000" style="mix-blend-mode: multiply">
<!--shape primitives that go on the key black layer-->
</g>
</svg>

这个结果是完美的……除了似乎我正在使用的程序之一不支持svg文件中的CSS。因此,我尝试使用feBlendfeComposite重新创建相同的效果。

<svg //put svg intro tag stuff here>
<defs>
<filter id="overcomp"><feComposite in="SourceGraphic" in2="BackgroundImage" operator="over" result="comp"/></filter>
<filter id="multiply"><feBlend mode="multiply" in2="BackgroundImage" in="SourceGraphic"/></filter>
</defs>
<rect width="100%" height="100%" fill="white"/>
<g fill="#0FF" filter="url(#overcomp)"> <!-- or #multiply)
<!--shape primitives that go on the cyan layer-->
</g>
<g fill="#F0F" filter="url(#overcomp)"> <!-- or #multiply)
<!--shape primitives that go on the magenta layer-->
</g>
<g fill="#FF0" filter="url(#overcomp)"> <!-- or #multiply)
<!--shape primitives that go on the yellow layer-->
</g>
<g fill="#000" filter="url(#overcomp)"> <!-- or #multiply)
<!--shape primitives that go on the key black layer-->
</g>
</svg>

滤镜似乎什么也没有做,并且结果的图像颜色没有混合。

每层都是20k +形状,因此,如果可能的话,我不希望重复定义。我该如何解决?

1 个答案:

答案 0 :(得分:0)

除IE10以外,BackgroundImage都不是任何浏览器的支持输入(并且SVG2已弃用)

您有三个选项可将这样的组拉入SVG过滤器。

第一个-可以在Firefox之外的所有环境中使用-是使用feImage和片段标识符将它们放入单个过滤器中。

<svg width="200px" height="200px">
<defs>

<g fill="#0FF" id="layer1"> 
<rect x="90" y="10" width="20" height="180"/>
</g>
<g fill="#F0F" id="layer2"> 
<circle cx="100" cy="100" r="80"/>
</g>
<g fill="#FF0" id="layer3">
<rect x="10" y="90" width="180" height="20"/>
</g>
<g fill="#000" id="layer4">
<path d="M 50 50 L150 50 L 150 150 L 50 150z"/>
</g>

<filter id="blendDefs">
<feImage xlink:href="#layer1" result="lay1"/>
<feImage xlink:href="#layer2" result="lay2"/>
<feImage xlink:href="#layer3" result="lay3"/>
<feImage xlink:href="#layer4" result="lay4"/>

<feBlend mode="multiply" in="lay1" in2="lay2" result="lay12"/>
<feBlend mode="multiply" in="lay3" in2="lay4" result="lay34"/>
<feBlend mode="multiply" in="lay12" in2="lay34" result="lay1234"/>
</filter>


</defs>

<rect filter="url(#blendDefs)" width="200" height="200" fill="none" stroke="none"/>

</svg>

第二个-这是一个技巧,但我要接受,是将每个组布置在单个SourceImage中的列(或行或网格)中,但使用feOffsets手动将它们覆盖在过滤器中。您必须通过在溢出上手动绘制一个rect来进行清理-因此下面是最后一个rect。 (您以前可以通过使用过滤器尺寸进行裁剪,但是显然Chrome现在可以将中间过滤器输出裁剪到过滤器窗口,因此您不能同时使用feOffset方法和过滤器裁剪。您也可以使用定位的feFloods覆盖过滤器中的内容-但在Chrome浏览器中也是如此。

<svg width="200px" height="800px">
<defs>

<filter id="blendOffset" >
<feOffset dy="0" result="lay1"/>
<feOffset dy="-200" result="lay2"/>
<feOffset dy="-200" result="lay3"/>
<feOffset dy="-200" result="lay4"/>

<feBlend mode="multiply" in="lay1" in2="lay2" result="lay12"/>
<feBlend mode="multiply" in="lay3" in2="lay4" result="lay34"/>
<feBlend mode="multiply" in="lay12" in2="lay34" result="lay1234"/>

</filter>
</defs>

<g id="OUTERCONTAINER" filter="url(#blendOffset)">
<rect x="0" y="0" height="800" width="200" fill="none" stroke="none"/>
<g fill="#0FF" > 
<rect x="90" y="10" width="20" height="180" />
</g>
<g fill="#F0F" > 
<circle cx="100" cy="100" r="80" transform="translate(0 200)"/>
</g>
<g fill="#FF0" >
<rect x="10" y="90" width="180" height="20" transform="translate(0 400)"/>
</g>
<g fill="#000">
<path d="M 50 50 L150 50 L 150 150 L 50 150z" transform="translate(0 600)"/>
</g>
</g>

<rect x="0" y="200" height="600" width="200" fill="#FFF" stroke="none"/>

</svg>

第三个-毫不费力-是将每个组作为每个feImage中的单独的image / svg URI内联。跨浏览器可正常工作-您的代码将如下所示

<feImage xlink:href="data:svg+xml; etc...."/>
<feImage xlink:href="data:svg+xml; etc...."/>
<feBlend in="layer2" in2="layer2" ... etc.