SVG background blur with polygon - html

I am trying to blur background with polygon svg shape. Below is svg. And here is Bin
<svg id="testSVG" style="position: absolute;left: 0;top: 0;height: 100%;width: 100%;opacity: 0.5;">
<defs>
<filter id="blurry" x="0%" y="0%" height="100%" width="100%" primitiveUnits="userSpaceOnUse">
<feGaussianBlur stdDeviation="5" in="SourceGraphic" result="blurSquares"></feGaussianBlur>
<feComponentTransfer in="blurSquares" result="opaqueBlur">
<feFuncA type="linear" intercept="1"></feFuncA>
</feComponentTransfer>
<feBlend mode="normal" in="opaqueBlur" in2="SourceGraphic"></feBlend>
</filter>
</defs>
<g filter="url(#blurry)">
<polygon points="0,0 100,0 100,200 0,200 0,0"></polygon>
</g>
</svg>
I am expecting to see part of background image blurred. But it is not working as expected. What changes are required to make it work?

There is no reliable way for a blur filter in an SVG to automatically blur something behind the SVG on the page.
To achieve what you want, the background image has to be copied into the SVG and the blur filter applied to that. Of course you would need to make sure that the image in the HTML and the version of it in the SVG line up correctly.
So, for example, here's a version of your example with a blurred image in the SVG. But no polygon yet.
html, body {
height: 100%;
width: 100%;
margin: 0px;
}
body {
background-image: url('http://wp.patheos.com.s3.amazonaws.com/blogs/faithwalkers/files/2013/03/bigstock-Test-word-on-white-keyboard-27134336.jpg');
}
<svg id="testSVG" style="position: absolute;left: 0;top: 0;height: 100%;width: 100%;">
<defs>
<filter id="blurry">
<feGaussianBlur stdDeviation="5" in="SourceGraphic"></feGaussianBlur>
</filter>
</defs>
<image x="0" y="0"
width="500" height="332"
xlink:href="http://wp.patheos.com.s3.amazonaws.com/blogs/faithwalkers/files/2013/03/bigstock-Test-word-on-white-keyboard-27134336.jpg"
filter="url(#blurry)" />
</svg>
Now if we want the blurred image to be inside the polygon, we can do that with a clipping path.
We turn the polygon into a clipping path and apply that to the blurred image.
html, body {
height: 100%;
width: 100%;
margin: 0px;
}
body {
background-image: url('http://wp.patheos.com.s3.amazonaws.com/blogs/faithwalkers/files/2013/03/bigstock-Test-word-on-white-keyboard-27134336.jpg');
}
<svg id="testSVG" style="position: absolute;left: 0;top: 0;height: 100%;width: 100%;">
<defs>
<filter id="blurry">
<feGaussianBlur stdDeviation="5" in="SourceGraphic"></feGaussianBlur>
</filter>
<clipPath id="polyclip">
<polygon points="50,200, 300,50, 400,300" />
</clipPath>
</defs>
<image x="0" y="0"
width="500" height="332"
xlink:href="http://wp.patheos.com.s3.amazonaws.com/blogs/faithwalkers/files/2013/03/bigstock-Test-word-on-white-keyboard-27134336.jpg"
filter="url(#blurry)"
clip-path="url(#polyclip)" />
</svg>
Note that I'm using a slightly more interesting triangle polygon here. So that the effect is more obvious.

Put This code in your Polygon Tag :
<polygon points="200,0 0,160 500,330" style="fill:lime;stroke:purple;stroke-width:1"></polygon>
html, body {
height: 100%;
width: 100%;
margin: 0px;
}
body {
background-image: url('http://wp.patheos.com.s3.amazonaws.com/blogs/faithwalkers/files/2013/03/bigstock-Test-word-on-white-keyboard-27134336.jpg');
}
<svg id="testSVG" style="position: absolute;left: 0;top: 0;height: 100%;width: 100%;opacity: 0.5;">
<defs>
<filter id="blurry" x="0%" y="0%" height="100%" width="100%" primitiveUnits="userSpaceOnUse">
<feGaussianBlur stdDeviation="5" in="SourceGraphic" result="blurSquares"></feGaussianBlur>
<feComponentTransfer in="blurSquares" result="opaqueBlur">
<feFuncA type="linear" intercept="1"></feFuncA>
</feComponentTransfer>
<feBlend mode="normal" in="opaqueBlur" in2="SourceGraphic"></feBlend>
</filter>
</defs>
<g filter="url(#blurry)">
<polygon points="200,0 0,160, 500,330" style="fill:lime;stroke:purple;stroke-width:1"></polygon>
</g>
</svg>

Your code works if you remove your feComponentTransfer and feBlend tags.
http://jsbin.com/tuyorotome/1/edit?html,css,output

Related

Svg shadow gets cut only when transforming parent with same dimensions

I have an svg which takes its parent width, but when I scale or rotate the parent the svg's drop shadow gets cut. The left one is fine, but when the parent is the same width and height of the svg (right one) it behaves different. I have overflow visible and filterUnits="userSpaceOnUse" http://jsfiddle.net/xrsknjfv/
scale.addEventListener("mousedown", function(){
this.parentElement.classList.toggle("scale");
})
svg{
fill: yellow;
overflow: visible;
width: 100%;
}
body > div{
position: absolute;
left: 50px;
top: 50px;
}
div > div{
display: inline-block;
width: 150px;
transition: 5s all;
}
div > div:nth-of-type(1){
padding: 15px;
}
div.scale > div{
transform: scale(0);
}
<div>
<button id="scale">
scale
</button>
<div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 409.96 254.59">
<defs>
<filter filterUnits="userSpaceOnUse" id="f1">
<feDropShadow filterUnits="userSpaceOnUse" dx="1.5" dy="0.8" stdDeviation="1"></feDropShadow>
</filter>
<filter filterUnits="userSpaceOnUse" id="f2">
<feDropShadow filterUnits="userSpaceOnUse" dx="-2" dy="1.8" stdDeviation="1"></feDropShadow>
</filter>
<filter filterUnits="userSpaceOnUse" id="f3">
<feDropShadow flood-opacity="0.1" stdDeviation="10" dy="-4" dx="-2" filterUnits="userSpaceOnUse"></feDropShadow>
</filter>
</defs>
<g style="filter: url(#f2);">
<g style="filter: url(#f3);">
<path d="M167.1,52.17S209.77-28.24,301.66,10.6c0,0,59.62,23.52,56.34,96.81,0,0,55.45,16.41,51.79,79.86,0,0-.3,61.95-67.65,67.28H220.75q-72.56,0-145.12,0C29.57,254.66-2.8,215,.19,170.31c0,0,7.74-70,81.58-68.37C81.77,101.94,101.46,42.87,167.1,52.17Z" style="filter: url(#f1);"></path>
</g>
</g>
</svg>
</div>
<div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 409.96 254.59">
<defs>
<filter filterUnits="userSpaceOnUse" id="f1">
<feDropShadow filterUnits="userSpaceOnUse" dx="1.5" dy="0.8" stdDeviation="1"></feDropShadow>
</filter>
<filter filterUnits="userSpaceOnUse" id="f2">
<feDropShadow filterUnits="userSpaceOnUse" dx="-2" dy="1.8" stdDeviation="1"></feDropShadow>
</filter>
<filter filterUnits="userSpaceOnUse" id="f3">
<feDropShadow flood-opacity="0.1" stdDeviation="10" dy="-4" dx="-2" filterUnits="userSpaceOnUse"></feDropShadow>
</filter>
</defs>
<g style="filter: url(#f2);">
<g style="filter: url(#f3);">
<path d="M167.1,52.17S209.77-28.24,301.66,10.6c0,0,59.62,23.52,56.34,96.81,0,0,55.45,16.41,51.79,79.86,0,0-.3,61.95-67.65,67.28H220.75q-72.56,0-145.12,0C29.57,254.66-2.8,215,.19,170.31c0,0,7.74-70,81.58-68.37C81.77,101.94,101.46,42.87,167.1,52.17Z" style="filter: url(#f1);"></path>
</g>
</g>
</svg>
</div>
</div>
Overflow shadows aren't retained during transform transitions - so you need to add margin/padding to your box to make sure they're ok.
Incidentally, you can make your SVG a lot terser
You don't need to re-declare filters within each inline SVG fragment
You only need to declare your filterUnits in the filter element itself (not each primitive)
You can use self-closing tags for feDropshadow ("/>")
You can get rid of the style and just declare a filter attribute directly.
<div>
<button id="scale">
scale
</button>
<div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 409.96 254.59">
<defs>
<filter id="f1" >
<feDropShadow dx="1.5" dy="0.8" stdDeviation="1"/>
</filter>
<filter id="f2">
<feDropShadow dx="-2" dy="1.8" stdDeviation="1"/>
</filter>
<filter id="f3" >
<feDropShadow stdDeviation="10" dy="-4" dx="-2"/>
</filter>
</defs>
<g filter="url(#f2)">
<g filter=" url(#f3)">
<path d="M167.1,52.17S209.77-28.24,301.66,10.6c0,0,59.62,23.52,56.34,96.81,0,0,55.45,16.41,51.79,79.86,0,0-.3,61.95-67.65,67.28H220.75q-72.56,0-145.12,0C29.57,254.66-2.8,215,.19,170.31c0,0,7.74-70,81.58-68.37C81.77,101.94,101.46,42.87,167.1,52.17Z" filter= "url(#f1)"></path>
</g>
</g>
</svg>
</div>
<div>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 409.96 254.59">
<g filter= "url(#f2)">
<g filter= "url(#f3)">
<path d="M167.1,52.17S209.77-28.24,301.66,10.6c0,0,59.62,23.52,56.34,96.81,0,0,55.45,16.41,51.79,79.86,0,0-.3,61.95-67.65,67.28H220.75q-72.56,0-145.12,0C29.57,254.66-2.8,215,.19,170.31c0,0,7.74-70,81.58-68.37C81.77,101.94,101.46,42.87,167.1,52.17Z" filter= "url(#f1)"></path>
</g>
</g>
</svg>
</div>
</div>

cannot apply drop shadow in IE11

how can i show in internet explorer 11 the same shadow that I can apply in chrome using this rule?
filter: drop-shadow(6px 6px 7px rgba(0,0,0,0.5));
This is my working chrome markup HTML
<div class="cta-image-container">
<div>
<svg class="svg-cta-image">
<image filter="url(#dropshadow)" width="640" height="580" class="cta-image cta-image-1-3" xlink:href="https://anekitalia.com/wp-content/uploads/media/justfun-viaggi-evento-viaggia-split.jpg"></image>
</svg>
</div>
<div>
<svg class="svg-cta-image">
<image width="640" height="580" class="cta-image cta-image-2-3" xlink:href="https://anekitalia.com/wp-content/uploads/media/justfun-viaggi-evento-viaggia-split.jpg"></image>
</svg>
</div>
<div>
<svg class="svg-cta-image">
<image width="640" height="580" class="cta-image cta-image-3-3" xlink:href="https://anekitalia.com/wp-content/uploads/media/justfun-viaggi-evento-viaggia-split.jpg"></image>
</svg>
</div>
<svg>
<defs>
<clipPath id="split-1-3">
<polygon points="222,580 0,580 0.12,0 176,0"></polygon>
</clipPath>
</defs>
</svg>
<svg>
<defs>
<clipPath id="split-2-3">
<polygon points="400,0 196,0 242,580 446,580"></polygon>
</clipPath>
</defs>
</svg>
<svg>
<defs>
<clipPath id="split-3-3">
<polygon points="640,0 420,0 466,580 640,580"></polygon>
</clipPath>
</defs>
</svg>
and this is the CSS
.cta-image-container svg{
position: absolute;
}
.cta-image-container {
width: 640px;
height: 580px;
margin: 0 25px 0 25px;
filter: drop-shadow(6px 6px 7px rgba(0,0,0,0.5));
position: relative;
}
.cta-image {
max-width: 100%;
max-height: 100%;
position: absolute;
}
.svg-cta-image {
width: 640px;
height: 580px;
}
.cta-image-1-3 {
clip-path: url(#split-1-3);
}
.cta-image-2-3 {
clip-path: url(#split-2-3);
}
.cta-image-3-3 {
clip-path: url(#split-3-3);
}
Here you can find a chrome working CODEPEN
As rx2347 pointed out, IE does not support CSS Filter Effects
So the only way to add a drop shadow is apply the effect inside your svg by using a blurred black polygon positioned behind the image.
This is an updated version of your codepen with the applied effect https://codepen.io/samwalker/pen/XWbzpZX
I don’t have a PC/IE 11 so I used BrowserStack to test and the results below:
Notes:
1. I had to increase the size of the viewbox/svg so the shadow wasn’t clipped
<svg class="svg-cta-image" viewBox="0 0 660 600">
2. Created the feGaussianBlur as an svg filter def.
<filter id="blurFilter">
<feGaussianBlur stdDeviation="5" />
<filter />
The 'blur size' is set by the stdDeviation attr.
A good tool to show what is possible with IE filters is Hands on: SVG filter Effects it’s part of Azure websites & shows MS IE compatible filters
3. Created a group element inside the SVG the same shape as clip-path, this is our 'shadow'
<g id="shadow" fill="black" filter="url(#blurFilter)" fill-opacity="0.5">
<polygon points="222,580 10,580 10,10 176,10"></polygon>
<polygon points="400,10 196,10 242,580 446,580"></polygon>
<polygon points="640,10 420,10 466,580 640,580"></polygon>
</g>
The shadow’s style is set with fill colour and fill-opacity.
I had to offset the polygon’s start points by 10px to match the new position of the image.
4. Combined the 3 polygons into a single clipping path so you only need to load the image once. If you are going to use 3 different images you can easily change this back.
5. Offset the image from the edge of the svg box and reset it’s size x="10" y="10" width="640" height="580", you maybe want to do this in the css.
There are probably some changes you’ll want to make but hopefully this will get you on the right path.
Full markup below:
.cta-image-container {
width: 660px;
height: 600px;
margin: 25px auto;
position: relative;
}
<div class="cta-image-container">
<div>
<svg class="svg-cta-image" viewBox="0 0 660 600"><!-- increased veiwbox by 20px so shadow isn’t clipped -->
<defs xmlns="http://www.w3.org/2000/svg">
<clipPath id="split-in-3"><!-- combined clipping path -->
<polygon points="222,580 0,580 0.12,0 176,0"></polygon>
<polygon points="400,0 196,0 242,580 446,580"></polygon>
<polygon points="640,0 420,0 466,580 640,580"></polygon>
</clipPath>
<filter id="blurFilter">
<feGaussianBlur stdDeviation="5" /><!-- size of shadow -->
<filter />
</defs>
<g id="shadow" fill="black" filter="url(#blurFilter)" fill-opacity="0.5"><!-- `fill` & `fill-opacity` set the shadow’s color -->
<polygon points="222,580 10,580 10,10 176,10"></polygon><!--`0`s replaced by 10 to offset shadow from edge of svg -->
<polygon points="400,10 196,10 242,580 446,580"></polygon>
<polygon points="640,10 420,10 466,580 640,580"></polygon>
</g>
<image clip-path="url(#split-in-3)" x="10" y="10" width="640" height="580" class="cta-image cta-image-1-3" xlink:href="https://anekitalia.com/wp-content/uploads/media/justfun-viaggi-evento-viaggia-split.jpg"></image><!-- positioned at 10px `x` & `y` to offset from edge of svg --><!-- reset size to match original -->
</svg>
</div>
</div>

svg shadow does not appear

I am having a problem with setting up shadow for a svg with mask applied to it. This is the code and jsfiddle: http://jsfiddle.net/3kxnmhfL/
.watch-video-svg {
width: 50px;
height: 50px;
}
<div class="watch-video-svg">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" height="100%" width="100%" viewBox="0 0 100 100">
<defs>
<filter id="shadow">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
<mask id="cut-off-bottom">
<circle cx="50%" cy="50%" r="50%" fill="white"/>
<polygon points="31,20, 31,77, 80,50" fill="black"/>
<!-- <rect x="0" y="0" width="200" height="200" fill="url(#Gradient)" /> -->
</mask>
</defs>
<circle cx="50%" cy="50%" r="50%" fill="red" mask="url(#cut-off-bottom)" filter="url(#shadow)" />
</svg>
</div>
I'd like the shadow to appear only around svg circle and not containing div.
What could be the reason for shadow not showing up?
SVG filters have a "filter region". The filter region defines the area of pixels that the browser uses to store the result of the filters. The default filter region is the bounds of the element (that the filter is applied to) plus a margin around it to allow for filter elements that have results larger than the original element.
By default, that margin is 10% of the width and height, applied to all four sides. However in your case, a stdDeviation of "4" causes the blur to extend further than that 10% margin allowance. The result is a clipped blur, even though the viewBox has been enlarged enough to cater for the full blur.
To fix, this, you just need to bump up the filter region size. An allowance of 20% seems to work okay:
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
In addition, I've simplified the SVG by getting rid of the unnecessary mask. I also tweaked the viewBox to include the part of the blur that extends to the left.
.watch-video-svg {
width: 500px;
height: 500px;
background: linen;
}
<div class="watch-video-svg">
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="-5 0 120 120">
<defs>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
</defs>
<circle cx="50" cy="50" r="50" fill="red" filter=url(#shadow) />
<polygon points="31,20, 31,77, 80,50" fill="white"/>
</svg>
</div>
You need to adjust your mask. Since your element is already a circle you don't need a circle in the mask, a rect to fill all the width/height is enough.
You need to also adjust the viewBox to leave some space for the shadow:
.watch-video-svg {
width: 50px;
height: 50px;
}
<div class="watch-video-svg">
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="0 0 120 120">
<defs>
<filter id="shadow">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
<mask id="cut-off-bottom">
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
<polygon points="31,20, 31,77, 80,50" fill="black"/>
</mask>
</defs>
<circle cx="50" cy="50" r="50" fill="red" mask="url(#cut-off-bottom)" filter=url(#shadow) />
</svg>
</div>

SVG image - fixed height - keep ratio - slice

I have a SVG that needs to have a fixed height so its not super big when the width is 2000+ pixels (widescreens...)
The clipping mask should always be visible and the background image should be sliced and not be stretchend, i tried several things but nothing seems to work.
This is what i have now:
https://codepen.io/bucky208/pen/OEqbPp
div {
width: 100%;
}
<div>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 1381.5" preserveAspectRatio="none" style="display: block; position: absolute; width: 100%;height: 400px;">
<g id="clipgroup">
<defs>
<polygon id="mask" points="0,572.1 0,1381.3 1024,1040.5 1024,337.6 0,0"/>
</defs>
<clipPath id="mask_1_">
<use xlink:href="#mask" style="overflow:visible;"/>
</clipPath>
<g style="clip-path:url(#mask_1_);">
<image style="overflow:visible;" width="331" height="444" id="theimage" xlink:href="https://image.ibb.co/ipbNkJ/56_E0406_E5_C8_EF897.jpg" transform="matrix(3.1119 0 0 3.1111 -3.0528 -2.604167e-04)"></image>
</g>
</g>
</svg>
</div>
Do i need another wrapper around everything? How do i restore the image ratio?
Kind regards and a big thank you for everyone trying to help.
In order to get image fills to fill their container but preserve the original aspect ratio, a filter combined with objectBoundingBox sizing and preserveAspectRatio is your friend. The following code does what I think you want:
svg {
background: red;
}
#svgcont {
position: absolute;
width: 100%;
}
<div id="svgcont">
<svg x="0" y="0" width="100%" height="800px">
<defs>
<filter id="image-fill-nostretch" primitiveUnits="objectBoundingBox">
<feImage x="0" y="0" width="1" height="1" id="theimage" xlink:href="https://image.ibb.co/ipbNkJ/56_E0406_E5_C8_EF897.jpg" preserveAspectRatio="xMidYMid slice"/>
<feComposite operator="in" x1="SourceGraphic"/>
</filter>
<clipPath id="mask_1_" clipPathUnits="objectBoundingBox">
<polygon id="mask" points="0,0.5 0,1 1,0.75 1,0.25 0,0"/>
</clipPath>
</defs>
<g clip-path="url(#mask_1_)">
<rect width="100%"height="100%" x="0%" y="0%" filter="url(#image-fill-nostretch)"/>
</g>
</svg>
</div>

SVG clip paths only work in firefox-- not chrome or safari?

I basically have two triangles that come together to make a rectangle (the height and width of the browser screen.
To do this I created two SVGs to apply to two divs.
However, this only works in firefox for some reason. When I try and view it in safari and chrome, the divs are hidden.
Please help! Why is this happening?
SVG 1:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="blur" x="0%" y="0%" width="100%" height="100%">
<feGaussianBlur stdDeviation="30" />
<feColorMatrix type="saturate" values="2" />
</filter>
<filter id="unblur">
<feGaussianBlur stdDeviation="0" />
<feColorMatrix type="saturate" values="3" />
</filter>
</defs>
<clipPath id="svgClip" clipPathUnits="objectBoundingBox">
<path id="svgPath" d="M0,0 L1,0 0,1z"/>
</clipPath>
<path id="svgMask" d="M0,0 L1,0 0,1z" />
</svg>
SVG 2:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="blur2" x="0%" y="0%" width="100%" height="100%">
<feGaussianBlur stdDeviation="30" />
<feColorMatrix type="saturate" values="2" />
</filter>
<filter id="unblur2">
<feGaussianBlur stdDeviation="0" />
<feColorMatrix type="saturate" values="3" />
</filter>
<clipPath id="svgClip2" clipPathUnits="objectBoundingBox">
<polygon points="0 1 1 0 1 1"/>
</clipPath>
</defs>
</svg>
CSS:
#top, #bottom{
background: url(img/1.JPG) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
height: 100%;
width: 100%;
position:absolute;
top:0px;
left:0px;
z-index: 2;}
#top{
-webkit-clip-path: url(clip.svg#svgClip);
-moz-clip-path: url(clip.svg#svgClip);
-o-clip-path: url(clip.svg#svgClip);
clip-path: url(clip.svg#svgClip);
filter: url(clip.svg#blur);}
#bottom{
-webkit-clip-path: url(clip2.svg#svgClip2);
-moz-clip-path: url(clip2.svg#svgClip2);
-o-clip-path: url(clip2.svg#svgClip2);
clip-path: url(clip2.svg#svgClip2);
filter: url(clip2.svg#blur2);}
HTML:
<div class="top"></div>
<div class="bottom"></div>
Thanks for the help in advance!
In Firefox SVG clip-paths can be applied to both html and SVG elements, this is an extension to the SVG and html specifications.
Chrome/Safari and other UAs can only currently be apply clip-paths to SVG elements. I expect that other UAs will support clipping non-SVG content at some point but I don't know when.
I suppose what you could do for non-firefox browsers is embed the <div> in an <svg><foreignObject></foreignObject></svg> wrapper and clip the <foreignObject> element.