SVG Смешивать цвета со всем фоном - PullRequest
0 голосов
/ 07 декабря 2018

Я уверен, что это действительно просто, но я делаю SVG, где у меня есть 4 <g> группы для каждого из цветов CMYK, и у меня есть все 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>

Этот результат идеален... за исключением того, что кажется, что CSS в файлах SVG не поддерживается ни в одной из программ, которые я использую.Поэтому я пытаюсь воссоздать точно такой же эффект, используя feBlend и feComposite.

<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 голосов
/ 08 декабря 2018

BackgroundImage не поддерживается для любого браузера, кроме IE10 (и устарел для 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, чтобы вручную наложить их внутри фильтра.Вы должны выполнить очистку, вручную нарисовав прямоугольник над переполнением - отсюда и последний прямоугольник ниже.(Раньше вы могли обрезать это, используя размеры фильтра, но, очевидно, 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>

Третий, который является громоздким, состоит в том, чтобы встроить каждую группу в виде отдельного URI изображения / SVG внутри каждого изображения.Это работает кросс-браузер - ваш код будет выглядеть так ...

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