Printing SVG which uses mix-blend-mode multiply - svg

I have an svg which uses mix-blend-mode: multiply. This svg is generated programmatically in the browser using JS.
<svg ref="svgElement" version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="500">
<circle cx="50" cy="50" r="40" stroke-width="4" fill="green" style="mix-blend-mode: multiply;" />
<circle cx="75" cy="75" r="40" stroke-width="4" fill="red" style="mix-blend-mode: multiply;" />
<circle cx="100" cy="50" r="40" stroke-width="4" fill="blue" style="mix-blend-mode: multiply;" />
</svg>
I can download this svg in the browser and would like to send that svg file to the printer (a professional printing company) but when they open the file in Illustrator or Photoshop etc. the multiply effect is not preserved.
Is there are way to overcome this in the client. I thought perhaps the svg could be flattened. Could this work?
Any help would be greatly appreciated.
Thanks,

You could try recasting this to only use SVG 1.1 capabilties - mix-blend-mode is new and I'm guessing that the Adobe tools don't render this properly yet.
So something like:
<svg ref="svgElement" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="500">
<defs>
<circle id="circ1"cx="50" cy="50" r="40" stroke-width="4" fill="green"/>
<circle id="circ2" cx="75" cy="75" r="40" stroke-width="4" fill="red"/>
<filter id="circle-blend" filterUnits="userSpaceOnUse" x="0" y="0" width="500" height="500" color-interpolation-filters="sRGB">
<feImage xlink:href="#circ1" result="circleInOne"/>
<feImage xlink:href="#circ2"/>
<feBlend mode="multiply" in2="circleInOne"/>
<feBlend mode="multiply" in2="SourceGraphic"/>
</filter>
</defs>
<circle filter="url(#circle-blend)" cx="100" cy="50" r="40" stroke-width="4" fill="blue"/>
</svg>

Related

SVG using non-repetitive pattern as fill

I'm trying to use different SVG elements with a pattern as a fill, but the pattern doesn't get repeated for every element. I'm not sure if there's the possibility to repeat the pattern, but right now it looks as if there's a pattern and three circles create a mask over the pattern. What I want to achieve is the three circles clearly looking differently because each pattern resets for each circle and then it doesn't look 'cut out'.
I suppose a last-resort solution would be to create multiple patterns with different names for every element I use, then it'll work, but I'm hoping there's a less cumbersome way.
I tried:
Wrapping each element in a different SVG container
Appending ids to the elements and then in css target every id separately with the fill being the url
I made a codesandbox which shows my problem:
https://codesandbox.io/s/busy-ives-hv3rr?file=/index.html
The solution #herrstrietzel posted is one way to go.
Another solution is to create variants of your original pattern, but with a different origin. You specify the origin using the x and y attributes.
<svg id="patternId" width="100%" height="100%">
<defs>
<pattern id="a" patternUnits="userSpaceOnUse" width="65" height="65" patternTransform="scale(2) rotate(0)">
<rect x="0" y="0" width="100%" height="100%" fill="hsla(0,0%,100%,1)"/>
<path d="M.5.5v12h12V.5H.5zm13 13v12h12v-12h-12zm-13 13v12h12v-12H.5zm26 13v12h12v-12h-12zm13 13v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(258.5,59.4%,59.4%,1)"/>
<path d="M26.5.5v12h12V.5h-12zm0 13v12h12v-12h-12zm13 13v12h12v-12h-12zm-39 13v12h12v-12H.5zm0 13v12h12v-12H.5z"
stroke-width="1" stroke="none" fill="hsla(339.6,82.2%,51.6%,1)"/>
<path d="M13.5.5v12h12V.5h-12zm39 13v12h12v-12h-12zm-39 13v12h12v-12h-12zm39 0v12h12v-12h-12zm-26 26v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(198.7,97.6%,48.4%,1)"/>
<path d="M52.5.5v12h12V.5h-12zm-13 13v12h12v-12h-12zm0 26v12h12v-12h-12zm13 0v12h12v-12h-12zm-39 13v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(33, 90%, 65%, 1)"/>
</pattern>
<pattern id="a2" href="#a" x="20" y="20"/>
<pattern id="a3" href="#a" x="45" y="50"/>
</defs>
<svg height="200" width="200">
<circle cx="50" cy="50" r="40" fill="url(#a)" />
</svg>
<svg height="200" width="200">
<circle cx="100" cy="50" r="40" fill="url(#a2)" />
</svg>
<svg height="200" width="200">
<circle cx="50" cy="100" r="40" fill="url(#a3)" />
</svg>
</svg>
Another alternative is to switch to objectBoundingBox units. So that the pattern is relative the the object it is applied to.
<svg id="patternId" width="100%" height="100%">
<defs>
<pattern id="a" patternUnits="objectBoundingBox" width="65" height="65">
<g transform="scale(2)">
<rect x="0" y="0" width="100%" height="100%" fill="hsla(0,0%,100%,1)"/>
<path d="M.5.5v12h12V.5H.5zm13 13v12h12v-12h-12zm-13 13v12h12v-12H.5zm26 13v12h12v-12h-12zm13 13v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(258.5,59.4%,59.4%,1)"/>
<path d="M26.5.5v12h12V.5h-12zm0 13v12h12v-12h-12zm13 13v12h12v-12h-12zm-39 13v12h12v-12H.5zm0 13v12h12v-12H.5z"
stroke-width="1" stroke="none" fill="hsla(339.6,82.2%,51.6%,1)"/>
<path d="M13.5.5v12h12V.5h-12zm39 13v12h12v-12h-12zm-39 13v12h12v-12h-12zm39 0v12h12v-12h-12zm-26 26v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(198.7,97.6%,48.4%,1)"/>
<path d="M52.5.5v12h12V.5h-12zm-13 13v12h12v-12h-12zm0 26v12h12v-12h-12zm13 0v12h12v-12h-12zm-39 13v12h12v-12h-12z"
stroke-width="1" stroke="none" fill="hsla(33, 90%, 65%, 1)"/>
</g>
</pattern>
<pattern id="a2" href="#a" x="20" y="20"/>
<pattern id="a3" href="#a" x="45" y="50"/>
</defs>
<svg height="200" width="200">
<circle cx="50" cy="50" r="40" fill="url(#a)" />
</svg>
<svg height="200" width="200">
<circle cx="100" cy="50" r="40" fill="url(#a)" />
</svg>
<svg height="200" width="200">
<circle cx="50" cy="100" r="40" fill="url(#a)" />
</svg>
</svg>
Applying transforms like transform="translate(50 50)" (instead of fixed x/y positioning would do the trick.
<svg id="patternId" width="100%" height="100%">
<defs>
<pattern id="pattern-0" patternUnits="userSpaceOnUse" width="65" height="65" patternTransform="scale(2) rotate(0)" >
<g id="patternInner">
<rect x="0" y="0" width="100%" height="100%" fill="hsla(0,0%,100%,1)" />
<path d="M.5.5v12h12V.5H.5zm13 13v12h12v-12h-12zm-13 13v12h12v-12H.5zm26 13v12h12v-12h-12zm13 13v12h12v-12h-12z" stroke-width="1" stroke="none" fill="hsla(258.5,59.4%,59.4%,1)" />
<path d="M26.5.5v12h12V.5h-12zm0 13v12h12v-12h-12zm13 13v12h12v-12h-12zm-39 13v12h12v-12H.5zm0 13v12h12v-12H.5z" stroke-width="1" stroke="none" fill="hsla(339.6,82.2%,51.6%,1)" />
<path d="M13.5.5v12h12V.5h-12zm39 13v12h12v-12h-12zm-39 13v12h12v-12h-12zm39 0v12h12v-12h-12zm-26 26v12h12v-12h-12z" stroke-width="1" stroke="none" fill="hsla(198.7,97.6%,48.4%,1)" />
<path d="M52.5.5v12h12V.5h-12zm-13 13v12h12v-12h-12zm0 26v12h12v-12h-12zm13 0v12h12v-12h-12zm-39 13v12h12v-12h-12z" stroke-width="1" stroke="none" fill="hsla(33, 90%, 65%, 1)" />
</g>
</pattern>
<pattern id="pattern-1" href="#pattern-0" x="80" y="80" patternTransform="scale(2) rotate(45)" />
</defs>
<circle cx="50" cy="50" r="40" fill="url(#pattern-0)" />
<circle cx="50" cy="50" r="50" fill="url(#pattern-0)" transform="translate(50 33)" />
<circle cx="50" cy="50" r="50" fill="url(#pattern-1)" transform="translate(50 33)" />
<rect x="0" y="0" width="50" height="50" stroke="#fff" stroke-width="1" transform="translate(10 60)" fill="url(#pattern-0)" />
</svg>
Worth noting: duplicating patterns for slightly modified usage is pretty straight forward, since the <pattern> element supports referencing/reusing previously defined patterns via href attribute (similar to <use>):
<pattern id="pattern-1" href="#pattern-0" x="80" y="80" patternTransform="scale(2) rotate(45)" />
Would result in a rotated pattern sharing all properties of the initially defined pattern.

why is size of text used as source in an SVG feComposite filter affected by the svg element size?

I'm trying to learn how to use feComposite in SVG, and in particular want to use text as one of the composition sources. Here's an initial sample of what I'm trying to do.
<svg width="100" height="100">
<defs>
<circle id="circ" cx="50" cy="50" r="40" stroke-width="0" fill="black" />
<text id="A" x="35" y="70" fill="black" style="font-size:60; font-family:Arial; font-weight:700">8</text>
<filter id="myfilter" width="120%">
<feImage xlink:href="#circ" result="lay1"/>
<feImage xlink:href="#A" result="lay2"/>
<feComposite operator="out" in="lay1" in2="lay2" result="COMP"/>
</filter>
</defs>
<g filter="url(#myfilter)" >
<use href="#circ"/>
<use href="#A"/>
</g>
</svg>
It gives me this result, as expected:
But, then I wanted to make everything bigger. So, I was going to need to increase the width and height on the svg element. However, when I do that, it causes the text to get smaller. Here's modified SVG, only increasing the height attribute on the svg element:
<svg width="100" height="150">
<defs>
<circle id="circ" cx="50" cy="50" r="40" stroke-width="0" fill="black" />
<text id="A" x="35" y="70" fill="black" style="font-size:60; font-family:Arial; font-weight:700">8</text>
<filter id="myfilter" width="120%">
<feImage xlink:href="#circ" result="lay1"/>
<feImage xlink:href="#A" result="lay2"/>
<feComposite operator="out" in="lay1" in2="lay2" result="COMP"/>
</filter>
</defs>
<g filter="url(#myfilter)" >
<use href="#circ"/>
<use href="#A"/>
</g>
</svg>
That caused the text content to scale smaller vertically.
If I increase the width on the svg element, then the text will scale smaller horizontally:
<svg width="150" height="150">
<defs>
<circle id="circ" cx="50" cy="50" r="40" stroke-width="0" fill="black" />
<text id="A" x="35" y="70" fill="black" style="font-size:60; font-family:Arial; font-weight:700">8</text>
<filter id="myfilter" width="120%">
<feImage xlink:href="#circ" result="lay1"/>
<feImage xlink:href="#A" result="lay2"/>
<feComposite operator="out" in="lay1" in2="lay2" result="COMP"/>
</filter>
</defs>
<g filter="url(#myfilter)" >
<use href="#circ"/>
<use href="#A"/>
</g>
</svg>
If instead of increasing the height or width on the svg element, I decrease the values, then the text will scale larger in the corresponding direction.
This only happens for text used as the filter source. If I use the same text element without the filter, it's not affected by changes in width/height on the svg root element. For example, in the following, I've modified the previous example by adding a <use> element to add another instance of the text (wrapped in a <g> with a translation lower on the page):
<svg width="150" height="150">
<defs>
<circle id="circ" cx="50" cy="50" r="40" stroke-width="0" fill="black" />
<text id="A" x="35" y="70" fill="black" style="font-size:60; font-family:Arial; font-weight:700">8</text>
<filter id="myfilter" width="120%">
<feImage xlink:href="#circ" result="lay1"/>
<feImage xlink:href="#A" result="lay2"/>
<feComposite operator="out" in="lay1" in2="lay2" result="COMP"/>
</filter>
</defs>
<rect x="0" y="40" width="100" height="20" fill="none"/>
<g filter="url(#myfilter)" >
<use href="#circ"/>
<use href="#A"/>
</g>
<g transform="translate(0,70)">
<use href="#A"/>
</g>
</svg>
What is going on here? Why is the text that's an feComposite source getting scaled based on the svg width/height?
In general, SVG filters are prone to screw ups when dimensions and units are unspecified. In this case, the g element is passing bad dimensions to the filter. For example, if you add a "y" coordinate to the first use element (the circle) inside the g element, and adjust its value, the text will shrink and expand.
Everything works fine if you explicitly add dimensions to everything and specify via preserveAspectRatio whether you want the aspect ratio of the input preserved or not. And if you want it preserved, whether you want it to size to the greater (meet) or the smaller (slice) dimension of the input.
Your filter actually discards the contents it was invoked with (its SourceGraphic) - so it doesn't really matter what you have in the g element - it's only using the contents to size the filter region (inconsistently as it turns out). So you may as well just apply a filter to a 100%/100% rect element - which you should size explicitly.
So, if you explicitly specify dimensions - this filter works just fine. I don't know what behavior you're trying to achieve. If you want the content to stay fixed as you expand the SVG element width/height - this is the filter you want.
<svg x="0" y="0" width="100px" height="150px" >
<defs>
<circle id="circ" cx="50" cy="50" r="40" stroke-width="0" fill="black" />
<text id="A" x="35" y="70" fill="black" style="font-size:60; font-family:Arial; font-weight:700">8</text>
<filter id="myfilter" filterUnits="userSpaceOnUse" primitiveUnits="objectBoundingBox" x="0" y="0" width="100" height="150">
<feImage x="0" y="0" height="1" width="1" xlink:href="#circ" result="lay1"/>
<feImage x="0" y="0" height="1" width="1" xlink:href="#A" result="lay2"/>
<feComposite operator="out" in="lay1" in2="lay2" result="COMP"/>
</filter>
</defs>
<rect filter="url(#myfilter)" x="0%" y="0%" width="100%" height="100%"/>
</svg>
<svg x="0" y="0" width="200px" height="250px" >
<defs>
<circle id="circ" cx="50" cy="50" r="40" stroke-width="0" fill="black" />
<text id="A" x="35" y="70" fill="black" style="font-size:60; font-family:Arial; font-weight:700">8</text>
<filter id="myfilter" filterUnits="userSpaceOnUse" primitiveUnits="objectBoundingBox" x="0" y="0" width="100" height="150">
<feImage x="0" y="0" height="1" width="1" xlink:href="#circ" result="lay1"/>
<feImage x="0" y="0" height="1" width="1" xlink:href="#A" result="lay2"/>
<feComposite operator="out" in="lay1" in2="lay2" result="COMP"/>
</filter>
</defs>
<rect filter="url(#myfilter)" x="0%" y="0%" width="100%" height="100%"/>
</svg>
On the other hand, if you want the content to scale, but keep its aspect ratio, you'll need a filter like this.
<svg x="0" y="0" width="100px" height="100px" viewBox="0 0 100 100" >
<defs>
<circle id="circ" cx="50" cy="50" r="40" stroke-width="0" fill="black" />
<text id="A" x="35" y="70" fill="black" style="font-size:60; font-family:Arial; font-weight:700">8</text>
<filter id="myfilter" primitiveUnits="objectBoundingBox" x="0" y="0" width="1" height="1">
<feImage x="0" y="0" height="1" width="1" xlink:href="#circ" result="lay1" preserveAspectRatio="xMidYMid slice"/>
<feImage x="0" y="0" height=".65 " width="1" xlink:href="#A" result="lay2" preserveAspectRatio="xMidYMid slice"/>
<feComposite operator="out" in="lay1" in2="lay2" result="COMP"/>
</filter>
</defs>
<rect filter="url(#myfilter)" x="0" y="0" width="100" height="150"/>
</svg>
<svg x="0" y="0" width="200px" height="250px" viewBox="0 0 100 100" >
<defs>
<circle id="circ" cx="50" cy="50" r="40" stroke-width="0" fill="black" />
<text id="A" x="35" y="70" fill="black" style="font-size:60; font-family:Arial; font-weight:700">8</text>
<filter id="myfilter" primitiveUnits="objectBoundingBox" x="0" y="0" width="1" height="1">
<feImage x="0" y="0" height="1" width="1" xlink:href="#circ" result="lay1" preserveAspectRatio="xMidYMid slice"/>
<feImage x="0" y="0" height=".65 " width="1" xlink:href="#A" result="lay2" preserveAspectRatio="xMidYMid slice"/>
<feComposite operator="out" in="lay1" in2="lay2" result="COMP"/>
</filter>
</defs>
<rect filter="url(#myfilter)" x="0" y="0" width="100" height="150"/>
</svg>

Make a path get cut off by a circle

Is there a way to cut off a path when it is outside of a circle?
<svg width="100" height="100">
<circle cx="50" cy="50" r="50" fill="red" />
<path d="M0 0 L100 100" stroke-width="1px" stroke="black" />
</svg>
Is it possible to make that line stay inside the circle (and not be visible off of the circle) without changing the d="M200 175 L696 880" in the path?
You can use a clipPath to prevent things drawing outside another shape.
<svg width="100" height="100">
<clipPath id="clip">
<circle cx="50" cy="50" r="50" fill="red" />
</clipPath>
<circle cx="50" cy="50" r="50" fill="red" />
<path d="M0 0 L100 100" stroke-width="1px" stroke="black" clip-path="url(#clip)"/>
</svg>

SVG pattern animation

I have defined a pattern in svg. I want to rotate it continuously.... I'm not able to apply animation on that pattern definition. i applied same animation to a symbol , it works but its not working on pattern...
<pattern id="GPattern"
x="10" y="10" width="20" height="20"
patternUnits="userSpaceOnUse"
patternTransform="rotate(35)"
>
<circle id="mycircle" cx="10" cy="10" r="10" style="stroke: none; fill: red" > </circle>
</pattern>
this is pattern def.
Please help me how i can apply certain transform animation to whole "pattern" as well as to individual contents of it.. in this case circle...
There doesn't seem to be anything stopping you dropping an <animateTransform> into the pattern definition:
<svg width="200" height="200" viewBox="0 0 200 200">
<defs>
<pattern id="GPattern" x="10" y="10" width="20" height="20"
patternUnits="userSpaceOnUse"
patternTransform="rotate(35)">
<animateTransform attributeType="xml"
attributeName="patternTransform"
type="rotate" from="35" to="395" begin="0"
dur="60s" repeatCount="indefinite"/>
<circle cx="10" cy="10" r="10" stroke="none" fill="red"/>
</pattern>
</defs>
<rect x="0" y="0" width="200" height="200" fill="url(#GPattern)"/>
</svg>

How to Exclude Area inside of clippath in Svg

I want to hide anything that outside a rectangle. (this i have achieved with clipping successfully). but another condition is that, 'also hide anything that comes inside the black big circle'. Now how i can achieve that?
in below example, 'yellow circle' must be eliminated'.
see below images for detail
Original:-
Desired:-
Below is my Svg code:-
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="500">
<g>
<rect x="50" y="50" width="200" height="200" stroke="1" fill="red"/>
<circle cx="180" cy="150" r="30" stroke="blue" />
</g>
<g clip-path = "url(#clip1)">
<circle cx="180" cy="150" r="10" stroke="blue" fill="yellow" />
</g>
<clipPath id = "clip1">
<rect x="50" y="50" width="200" height="200" stroke="1" fill="red"/>
</clipPath>
</svg>
Erik Dahlström is right, your clip can include the entire rectangle and the cutout for the circle. This way, anything you associate with #clip1 as the clip-path will not be visible inside your circle area. Here is what it looks like for your example:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="500">
<g>
<rect x="50" y="50" width="200" height="200" stroke="1" fill="red"/>
<circle cx="180" cy="150" r="30" stroke="blue" />
</g>
<g clip-path = "url(#clip1)">
<circle cx="180" cy="150" r="10" stroke="blue" fill="yellow" />
</g>
<clipPath id = "clip1">
<path d="M 50,50 l200 0 l0 200 l-200 0z M150,150 a30,30 1 0,0 60,0z M210,150 a30,30 1 0,0 -60,0z"/>
</clipPath>

Resources