SVG using non-repetitive pattern as fill - svg

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.

Related

Printing SVG which uses mix-blend-mode multiply

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>

How to change the color of one or more element that is part of a SVG pattern?

I have the following SVG code which draws many squares:
<svg width="100%" height="100%" viewBox="0,0,100%,100%" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="smallGrid" width="1.388888888888889%" height="5%" patternUnits="userSpaceOnUse">
<path fill="#2e99e5" d="M0 0h960v960H0z" stroke="gray" stroke-width="0.5"/>
</pattern>
<pattern id="grid" width="8.333333333333333%" height="50%" patternUnits="userSpaceOnUse">
<rect width="100%" height="100%" fill="url(#smallGrid)"/>
<path fill="none" d="M0 0h960v960H0z" stroke="gray" stroke-width="2" />
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#grid)" />
</svg>
Is there a way to select the first 3 <path fill="#2e99e5" d="M0 0h960v960H0z" stroke="gray" stroke-width="0.5"/>
and change the color?

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