SVG Blend color with entire background - svg

I'm sure this is really simple, but I'm making a SVG, where I have 4 <g> groups for each of CMYK colors and I'm having all 4 composited on top of each other.
I want to use a multiply color blending mode for each layer; each layer is its own solid color for each of CMYK, and I'd like the colors blended to produce the final image.
Using CSS I do:
<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>
This result is perfect... except it seems css in svg files isn't supported in one of the programs I'm using. So I'm trying to recreate this exact same effect using feBlend and 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>
The filter doesn't seem to do anything and the resultant image colors are not blended.
Each layer is 20k+ shapes so I would prefer not to duplicate the definitions if possible. How do I fix this?

BackgroundImage is not a supported input for any browser except IE10 (and has been deprecated for SVG2)
You have three options for pulling in groups like this into a SVG filter.
The first - which works everywhere except Firefox - is to pull them into a single filter using feImage and a fragment identifier.
<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>
The second - which is a hack, but bear with me, is to lay out each group in a column (or a row or a grid) within a single SourceImage, but use feOffsets to manually overlay them inside the filter. You have to do cleanup by manually drawing a rect over the overflow - hence the final rect below. (You used to be able to clip this by using filter dimensions but apparently Chrome now clips intermediate filter outputs to the filter window, so you can't use the feOffset method and filter clipping together. You also used to be able to use positioned feFloods to overpaint stuff inside a filter - but that's also broken in 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>
The third- which is unwieldly - is to inline each group as a separate image/svg URI within each feImage. This works cross browser - your code will look like this ...
<feImage xlink:href="data:svg+xml; etc...."/>
<feImage xlink:href="data:svg+xml; etc...."/>
<feBlend in="layer2" in2="layer2" ... etc.

Related

How do I stop svg GaussianBlur from being clipped? [duplicate]

Why does the grid in this SVG not fill the entire 256x256 space? No matter what size I change it to, about 15% of the grid is cut off, which appears to me to be arbitrary in the context of my code.
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="grid" width="18.75" height="18.75" patternUnits="userSpaceOnUse">
<path d="M 18.75 0 L 0 0 0 18.75" fill="none" stroke="black" stroke-width="1"/>
</pattern>
<rect id="gridRect" width="100%" height="100%" fill="url(#grid)" />
<filter id="gridify" width="100%" height="100%" filterUnits = "userSpaceOnUse">
<feImage result="sourceTwo" xlink:href="#gridRect" />
<feComposite in="SourceGraphic" in2="sourceTwo" operator="in"/>
</filter>
</defs>
<g filter="url(#gridify)" >
<rect width="100%" height="100%" fill="url(#linGradient)" />
</g>
<rect width="100%" height="100%" fill="none" stroke="black" stroke-width="1"/>
</svg>
The SVG specification defaults filters to being 10% larger than the filtered object by default.
If ‘x’ or ‘y’ is not specified, the effect is as if a value of -10% were specified.
If ‘width’ or ‘height’ is not specified, the effect is as if a value of 120% were specified.
I imagine that's to stop lots of questions along the lines of "why is my Gaussian blur based drop-shadow filter cut off?"
So, looks like all I needed to do to fix it was add an x="0" and a y="0" to the filter. I don't understand why it is necessary though, as it does not make sense that it would default to "-15%".
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="grid" width="18.75" height="18.75" patternUnits="userSpaceOnUse">
<path d="M 18.75 0 L 0 0 0 18.75" fill="none" stroke="black" stroke-width="1"/>
</pattern>
<rect id="gridRect" width="100%" height="100%" fill="url(#grid)" />
<filter id="gridify" x="0" y="0" width="100%" height="100%" filterUnits = "userSpaceOnUse">
<feImage result="sourceTwo" xlink:href="#gridRect" />
<feComposite in="SourceGraphic" in2="sourceTwo" operator="in"/>
</filter>
</defs>
<g filter="url(#gridify)" >
<rect width="100%" height="100%" fill="url(#linGradient)" />
</g>
<rect width="100%" height="100%" fill="none" stroke="black" stroke-width="1"/>
</svg>

Apply a texture to an image in SVG

I'm trying to apply a texture to an image
Original
Texture
Result (made with PHP GD)
But with SVG, the closest I got is this result
<svg preserveAspectRatio="none" width="500" height="500" viewBox="0 0 500 500">
<defs>
<filter id="texture">
<feImage href="https://i.imgur.com/pjWcnJs.jpg" result="texture-img"/>
<feBlend in="SourceGraphic" in2="texture-img" mode="multiply"/>
</filter>
</defs>
<g>
<g filter="url(#texture)">
<image x="0" y="0" href="https://i.imgur.com/oVEdsQt.png" opacity="1" width="500" height="500" />
</g>
</g>
</svg>
fiddle
Is there another way which won't texturize transparent pixels?
I found a solution which is to pass the texture through a composite filter which would crop it to the source image
<svg preserveAspectRatio="none" width="500" height="500" viewBox="0 0 500 500">
<defs>
<filter id="texture">
<feImage href="https://i.imgur.com/pjWcnJs.jpg" result="texture-img"/>
<feComposite in2="SourceGraphic" operator="in" in="texture-img" result="composite"/>
<feBlend in="SourceGraphic" in2="composite" mode="multiply"/>
</filter>
</defs>
<g>
<g filter="url(#texture)">
<image x="0" y="0" href="https://i.imgur.com/oVEdsQt.png" opacity="1" width="500" height="500" />
</g>
</g>
</svg>
To tile the texture, I used feTile like this
<svg preserveAspectRatio="none" width="500" height="500" viewBox="0 0 500 500">
<defs>
<filter id="texture" x="0" y="0" width="100%" height="100%">
<feImage href="https://i.imgur.com/gWH7NLm.jpg" result="texture-img" width="256" height="256"/>
<feTile in="texture-img" x="0" y="0" width="100%" height="100%" result="tile" ></feTile>
<feComposite in2="SourceGraphic" operator="in" in="tile" result="composite"/>
<feBlend in="SourceGraphic" in2="composite" mode="multiply"/>
</filter>
</defs>
<g>
<g filter="url(#texture)">
<image x="0" y="0" href="https://i.imgur.com/oVEdsQt.png" opacity="1" width="500" height="500" />
</g>
</g>
</svg>
I got the idea by checking how inkscape applies material textures

SVG path mask not working

According to example of this tutorials I want to mask my icon (black and white) instead of text in this tutorial. but right side of icon is still dark. how can I make left side of my icon black stroke and right side of icon goes white stroke?
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="41px" height="50px" viewbox="-3 -3 40 48">
<defs>
<mask id="myMask" maskUnits="userSpaceOnUse"
x="0" y="0" width="18" height="50">
<rect x="0" y="0" width="15" height="50" fill="white"/>
</mask>
<path id="fire-icon" d="m 25.55134,17.573125 c 0.647761,1.273107 1.136636,2.596633 1.344412,4.021007 0.21999,1.47479 0.13444,2.924371 -0.342217,4.348739 -0.427768,1.273111 -1.124413,2.382358 -2.004391,3.378155 -0.977758,1.096637 -2.114394,1.991591 -3.348802,2.773105 -0.183328,0.113445 -0.366658,0.226895 -0.57443,0.365546 1.429964,-3.214282 1.686623,-5.760501 0.366659,-8.924365 -0.904421,-2.155462 -2.395495,-3.743696 -3.519909,-4.4874 0,0 0.305545,3.655466 -2.248829,5.9874 0.391098,-1.184876 -0.672208,-2.31933 -0.672208,-2.31933 -0.31777,1.386549 -0.8922,1.651268 -1.662178,2.836135 -0.366658,0.567227 -0.708873,1.159666 -0.941085,1.802516 -0.342214,0.970596 -0.403325,1.953785 -0.207778,2.96219 0.134444,0.668067 0.342218,1.310925 0.63554,1.941174 0.02446,0.05042 0.04889,0.113449 0.08556,0.226893 C 12.156129,32.308418 11.899468,32.169763 11.655035,31.993294 10.921719,31.463881 10.163961,30.959677 9.467313,30.37985 8.5628918,29.623547 7.8173555,28.715982 7.3284794,27.619344 7.0351536,26.951277 6.8640469,26.245395 6.8151593,25.514301 c -0.097775,-1.65126 0.2933257,-3.201685 0.9899743,-4.676472 0.5010979,-1.071427 0.9777525,-2.142852 1.4544067,-3.226887 0.1344411,-0.31513 0.2199942,-0.66807 0.3055478,-1.008411 0.085554,-0.327726 0.1344412,-0.668063 0.1955503,-1.033609 0.9777516,0.46639 1.4544056,2.521009 0.9044216,3.857144 0.02444,0 0.03666,0 0.06111,0 0.232216,-0.302517 0.464431,-0.605039 0.696652,-0.907563 0.977751,-1.323526 1.869945,-2.684872 2.566595,-4.184872 0.623316,-1.34874 1.099973,-2.735295 1.185527,-4.247902 0.02445,-0.5294123 -0.02445,-1.0714263 -0.03667,-1.6008383 0.01223,0 0.02445,0 0.03667,0 0.65998,0.315125 1.307741,0.680673 1.882172,1.134457 1.014423,0.8193243 1.857728,1.7899163 2.566601,2.8991563 0.892198,1.411766 1.515512,2.936975 1.955505,4.550418 0.01223,0.06302 0.03667,0.126055 0.06111,0.214286 1.344407,-1.210083 0.513317,-4.172266 0.501096,-4.222688 -0.02445,-0.0252 2.261053,2.029411 3.409911,4.512605 z"
fill="none" stroke="#303233" stroke-width="1.3" />
</defs>
<!-- Draw black rectangle in the background -->
<rect x="18" y="0" width="15" height="50" fill="#000" />
<!-- Draw the text string twice. First, the white text without mask.
Second, the black text with the mask applied-->
<use xlink:href="#fire-icon" stroke="white"/>
<use xlink:href="#fire-icon" stroke="black" mask="url(#myMask)"/>
</svg>
There's no mask issue. The stroke on the path overrides the stroke on the use element, so in the question there are two grey (#303233) stroked paths. Removing the path stroke atribute allows the use to set one.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="41px" height="50px" viewbox="-3 -3 40 48">
<defs>
<mask id="myMask" maskUnits="userSpaceOnUse"
x="0" y="0" width="18" height="50">
<rect x="0" y="0" width="15" height="50" fill="white"/>
</mask>
<path id="fire-icon" d="m 25.55134,17.573125 c 0.647761,1.273107 1.136636,2.596633 1.344412,4.021007 0.21999,1.47479 0.13444,2.924371 -0.342217,4.348739 -0.427768,1.273111 -1.124413,2.382358 -2.004391,3.378155 -0.977758,1.096637 -2.114394,1.991591 -3.348802,2.773105 -0.183328,0.113445 -0.366658,0.226895 -0.57443,0.365546 1.429964,-3.214282 1.686623,-5.760501 0.366659,-8.924365 -0.904421,-2.155462 -2.395495,-3.743696 -3.519909,-4.4874 0,0 0.305545,3.655466 -2.248829,5.9874 0.391098,-1.184876 -0.672208,-2.31933 -0.672208,-2.31933 -0.31777,1.386549 -0.8922,1.651268 -1.662178,2.836135 -0.366658,0.567227 -0.708873,1.159666 -0.941085,1.802516 -0.342214,0.970596 -0.403325,1.953785 -0.207778,2.96219 0.134444,0.668067 0.342218,1.310925 0.63554,1.941174 0.02446,0.05042 0.04889,0.113449 0.08556,0.226893 C 12.156129,32.308418 11.899468,32.169763 11.655035,31.993294 10.921719,31.463881 10.163961,30.959677 9.467313,30.37985 8.5628918,29.623547 7.8173555,28.715982 7.3284794,27.619344 7.0351536,26.951277 6.8640469,26.245395 6.8151593,25.514301 c -0.097775,-1.65126 0.2933257,-3.201685 0.9899743,-4.676472 0.5010979,-1.071427 0.9777525,-2.142852 1.4544067,-3.226887 0.1344411,-0.31513 0.2199942,-0.66807 0.3055478,-1.008411 0.085554,-0.327726 0.1344412,-0.668063 0.1955503,-1.033609 0.9777516,0.46639 1.4544056,2.521009 0.9044216,3.857144 0.02444,0 0.03666,0 0.06111,0 0.232216,-0.302517 0.464431,-0.605039 0.696652,-0.907563 0.977751,-1.323526 1.869945,-2.684872 2.566595,-4.184872 0.623316,-1.34874 1.099973,-2.735295 1.185527,-4.247902 0.02445,-0.5294123 -0.02445,-1.0714263 -0.03667,-1.6008383 0.01223,0 0.02445,0 0.03667,0 0.65998,0.315125 1.307741,0.680673 1.882172,1.134457 1.014423,0.8193243 1.857728,1.7899163 2.566601,2.8991563 0.892198,1.411766 1.515512,2.936975 1.955505,4.550418 0.01223,0.06302 0.03667,0.126055 0.06111,0.214286 1.344407,-1.210083 0.513317,-4.172266 0.501096,-4.222688 -0.02445,-0.0252 2.261053,2.029411 3.409911,4.512605 z"
fill="none" stroke-width="1.3" />
</defs>
<!-- Draw black rectangle in the background -->
<rect x="18" y="0" width="15" height="50" fill="#000" />
<!-- Draw the text string twice. First, the white text without mask.
Second, the black text with the mask applied-->
<use xlink:href="#fire-icon" stroke="white"/>
<use xlink:href="#fire-icon" stroke="black" mask="url(#myMask)"/>
</svg>

SVG: draw text with solid background color [duplicate]

I want to color the background of svg text similar to background-color in css
I was only able to find documentation on fill, which colors the text itself
Is it even possible?
You could use a filter to generate the background.
<svg width="100%" height="100%">
<defs>
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="yellow" result="bg" />
<feMerge>
<feMergeNode in="bg"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<text filter="url(#solid)" x="20" y="50" font-size="50">solid background</text>
</svg>
No this is not possible, SVG elements do not have background-... presentation attributes.
To simulate this effect you could draw a rectangle behind the text attribute with fill="green" or something similar (filters). Using JavaScript you could do the following:
var ctx = document.getElementById("the-svg"),
textElm = ctx.getElementById("the-text"),
SVGRect = textElm.getBBox();
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
rect.setAttribute("x", SVGRect.x);
rect.setAttribute("y", SVGRect.y);
rect.setAttribute("width", SVGRect.width);
rect.setAttribute("height", SVGRect.height);
rect.setAttribute("fill", "yellow");
ctx.insertBefore(rect, textElm);
The solution I have used is:
<svg>
<line x1="100" y1="100" x2="500" y2="100" style="stroke:black; stroke-width: 2"/>
<text x="150" y="105" style="stroke:white; stroke-width:0.6em">Hello World!</text>
<text x="150" y="105" style="fill:black">Hello World!</text>
</svg>
A duplicate text item is being placed, with stroke and stroke-width attributes. The stroke should match the background colour, and the stroke-width should be just big enough to create a "splodge" on which to write the actual text.
A bit of a hack and there are potential issues, but works for me!
Instead of using a <text> tag, the <foreignObject> tag can be used, which allows for XHTML content with CSS.
No, you can not add background color to SVG elements. You can do it programmatically with d3.
var text = d3.select("text");
var bbox = text.node().getBBox();
var padding = 2;
var rect = self.svg.insert("rect", "text")
.attr("x", bbox.x - padding)
.attr("y", bbox.y - padding)
.attr("width", bbox.width + (padding*2))
.attr("height", bbox.height + (padding*2))
.style("fill", "red");
Answer by Robert Longson (#RobertLongson) with modifications:
<svg width="100%" height="100%">
<defs>
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="yellow"/>
<feComposite in="SourceGraphic" operator="xor"/>
</filter>
</defs>
<text filter="url(#solid)" x="20" y="50" font-size="50"> solid background </text>
<text x="20" y="50" font-size="50">solid background</text>
</svg>
and we have no bluring and no heavy "getBBox" :)
Padding is provided by white spaces in text-element with filter.
It's worked for me
Going further with #dbarton_uk answer, to avoid duplicating text you can use paint-order=stroke style:
<svg>
<line x1="100" y1="100" x2="350" y2="100" style="stroke:grey; stroke-width: 100"/>
<text x="150" y="105" style="stroke:white; stroke-width:0.5em; fill:black; paint-order:stroke; stroke-linejoin:round">Hello World!</text>
</svg>
Note the stroke-linejoin:round which is needed to avoid seeing spikes for the W sharp angle.
You can combine filter with the text.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>SVG colored patterns via mask</title>
</head>
<body>
<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter x="0" y="0" width="1" height="1" id="bg-text">
<feFlood flood-color="white"/>
<feComposite in="SourceGraphic" operator="xor" />
</filter>
</defs>
<!-- something has already existed -->
<rect fill="red" x="150" y="20" width="100" height="50" />
<circle cx="50" cy="50" r="50" fill="blue"/>
<!-- Text render here -->
<text filter="url(#bg-text)" fill="black" x="20" y="50" font-size="30">text with color</text>
<text fill="black" x="20" y="50" font-size="30">text with color</text>
</svg>
</body>
</html>
this is my favorite hack (not sure it should work). It refer an element that is not yet displayed, and it works pretty well
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 620 40" preserveAspectRatio="xMidYMid meet">
<defs>
<filter x="-0.02" y="0" width="1.04" height="1.1" id="removebackground">
<feFlood flood-color="#00ffff"/>
</filter>
</defs>
<!--Draw the text-->
<use xlink:href="#mygroup" filter="url(#removebackground)" />
<g id="mygroup">
<text id="text1" x="9" y="20" style="text-anchor:start;font-size:14px;">custom text with background</text>
<line x1="200" y1="18" x2="200" y2="36" stroke="#000" stroke-width="5"/>
<line x1="120" y1="27" x2="203" y2="27" stroke="#000" stroke-width="5"/>
</g>
</svg>
For those wondering how to apply padding to a text element when it has a background like in the Robert's answer, do the following:
<svg>
<defs>
<filter x="-0.1" y="-0.1" width="1.2" height="1.2" id="solid">
<feFlood flood-color="#171717"/>
<feComposite in="SourceGraphic" operator="xor" />
</filter>
</defs>
<text filter="url(#solid)" x="20" y="50" font-size="50">Hello</text>
</svg>
In the example above, filter's x and y positions can be used as transform: translate(-10%, -10%) would, and width and height values can be read as 120% and 120%. So we made background 20% bigger, and offsetted it -10%, so background is now 10% bigger on each side of the text.
The previous answers relied on doubling up text and lacked sufficient whitespace.
By using atop and I was able to get the results I wanted.
This example also includes arrows, a common use case for SVG text labels:
<svg viewBox="-105 -40 210 234">
<title>Size Guide</title>
<defs>
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="white"></feFlood>
<feComposite in="SourceGraphic" operator="atop"></feComposite>
</filter>
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z"></path>
</marker>
</defs>
<g id="garment">
<path id="right-body" fill="none" stroke="black" stroke-width="1" stroke-linejoin="round" d="M0 0 l30 0 l0 154 l-30 0"></path>
<path id="right-sleeve" d="M30 0 l35 0 l0 120 l-35 0" fill="none" stroke-linejoin="round" stroke="black" stroke-width="1"></path>
<use id="left-body" href="#right-body" transform="scale(-1,1)"></use>
<use id="left-sleeve" href="#right-sleeve" transform="scale(-1,1)"></use>
<path id="collar-right-top" fill="none" stroke="black" stroke-width="1" stroke-linejoin="round" d="M0 -6.5 l11.75 0 l6.5 6.5"></path>
<use id="collar-left-top" href="#collar-right-top" transform="scale(-1,1)"></use>
<path id="collar-left" fill="white" stroke="black" stroke-width="1" stroke-linejoin="round" d="M-11.75 -6.5 l-6.5 6.5 l30 77 l6.5 -6.5 Z"></path>
<path id="front-right" fill="white" stroke="black" stroke-width="1" d="M18.25 0 L30 0 l0 154 l-41.75 0 l0 -77 Z"></path>
<line x1="0" y1="0" x2="0" y2="154" stroke="black" stroke-width="1" stroke-dasharray="1 3"></line>
<use id="collar-right" href="#collar-left" transform="scale(-1,1)"></use>
</g>
<g id="dimension-labels">
<g id="dimension-sleeve-length">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="85" y1="0" x2="85" y2="120" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="85" y="60" class="dimension" text-anchor="middle" dominant-baseline="middle"> 120 cm</text>
</g>
<g id="dimension-length">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-85" y1="0" x2="-85" y2="154" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="-85" y="77" text-anchor="middle" dominant-baseline="middle" class="dimension"> 154 cm</text>
</g>
<g id="dimension-sleeve-to-sleeve">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-65" y1="-20" x2="65" y2="-20" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="0" y="-20" text-anchor="middle" dominant-baseline="middle" class="dimension"> 130 cm </text>
</g>
<g title="Back Width" id="dimension-back-width">
<line marker-start="url(#arrow)" marker-end="url(#arrow)" x1="-30" y1="174" x2="30" y2="174" stroke="black" stroke-width="1"></line>
<text font-size="10" filter="url(#solid)" fill="black" x="0" y="174" text-anchor="middle" dominant-baseline="middle" class="dimension"> 60 cm </text>
</g>
</g>
</svg>
An obvious workaround to the problem of the blur produced by the filter effect is to render the <text> two times: once for the background (with transparent characters) and once for the characters (without a background filter).
For me, this was the only way to make the text readable in Safari.
<svg width="100%" height="100%">
<filter x="0" y="0" width="1" height="1" id="solid">
<feFlood flood-color="yellow" />
</filter>
<g transform="translate(20, 50)" font-size="50">
<text aria-hidden="true" fill="none" filter="url(#solid)">solid background</text>
<text fill="blue">solid background</text>
</g>
</svg>
The aria-hidden="true" attribute is there to prevent screen readers from speaking the text twice, if the user uses a screen reader.
You can add style to your text:
style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
text-shadow: rgb(255, 255, 255) -2px -2px 0px, rgb(255, 255, 255) -2px 2px 0px,
rgb(255, 255, 255) 2px -2px 0px, rgb(255, 255, 255) 2px 2px 0px;"
White, in this example.
Does not work in IE :)

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