I am trying to apply a Vignette effect on images with SVG filters. I am trying to implement this with the <fePointLight> primitive, but I find this a bit limited in that it is always has a circular shape. Is it possible to change the width such that the lighting effect takes on a wide elliptical shape? This is currently the filter I am using:
<filter id="vignette">
<feFlood id="flood-5" result="blackfield-6" x="0%" y="0%" width="100%" height="100%" flood-color="#000000" flood-opacity="1"/>
<feSpecularLighting id="specular-5" result="Spotlight-6" lighting-color="#FFFFFF" surfaceScale="1" specularConstant="1" specularExponent="100">
<fePointLight id="pointlight-5" x="720" y="450" z="1200"/>
</feSpecularLighting>
<feBlend id="svg-7" result="A-6" in="blackfield-6" in2="Spotlight-6" mode="lighten"/>
<feBlend id="blend-5" result="B-6" in="A-6" in2="SourceGraphic" mode="multiply"/>
</filter>
I am aware that it is possible to do this with a radial gradient effect on a separate shape, but I have a requirement that it must be done purely using SVG filters.
The values of the x=350 and y=240 attributes of the fePointLight filter are chosen so that the point is in the center of the image.
Different values for the z attribute of the fePointLight filter render the light source at different depths in relation to the drawing. The nearest position corresponds to the largest size.
Please watch in full screen
Hover over image
#img {
width:700px;
height:481px;
}
#img:hover {
filter:url(#spotlight);
}
<img id="img" src="https://i.stack.imgur.com/mBuDo.jpg" >
<svg width="700" height="481" viewBox="0 0 700 481" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="spotlight">
<feSpecularLighting result="spotlight" specularConstant="3.5"
specularExponent="70" lighting-color="grey">
<fePointLight x="350" y="240" z="520"/>
</feSpecularLighting>
<feComposite in="SourceGraphic" in2="spotlight" operator="in"/>
</filter>
</defs>
</svg>
Other image
#img {
width:700px;
height:481px;
}
#img:hover {
filter:url(#spotlight);
}
<img id="img" src="https://i.stack.imgur.com/GlhkD.jpg" >
<svg width="700" height="481" viewBox="0 0 700 481" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="spotlight">
<feSpecularLighting result="spotlight" specularConstant="3.5"
specularExponent="70" lighting-color="grey">
<fePointLight x="350" y="240" z="520"/>
</feSpecularLighting>
<feComposite in="SourceGraphic" in2="spotlight" operator="in"/>
</filter>
</defs>
If you want that sort of effect (elliptical light), you probably want to be using a spotlight rather than a point light.
If you offset the light position to one side and shine the cone down at a shallow-ish angle, you will get an elliptical spot.
<svg width="600" height="529">
<defs>
<filter id="spotlight">
<feSpecularLighting result="spotlight" specularConstant="1.5"
specularExponent="4" lighting-color="#FFF">
<feSpotLight x="-200" y="265" z="400" limitingConeAngle="10" pointsAtX="300" pointsAtY="265" />
</feSpecularLighting>
<feComposite in="SourceGraphic" in2="spotlight" operator="out" k1="0" k2="1" k3="1" k4="0"/>
</filter>
</defs>
<rect x="0" y="0" width="600" height="529" style="fill: skyblue; filter:url(#spotlight);"/>
</svg>
Note that the lighting filter components can be unreliable to use. Each browser has differences in interpretation of the standard. Not to mention some bugs.
A point in case is the above example, which looks different in Firefox and Chrome.
But good luck with your project.
I have tried removing the
<!-- DILATED TEXT -->
<text font-size="85px" dx="125" dy="130" font-weight="700" filter="url(#outline)">upgrade yourself</text>
<feMergeNode in="SourceGraphic" /> and in="SourceAlpha" parts in the code, so that it would apply to the element to which is referenced via CSS, but it just wipes the text out, and it doesn't produce the outline that it's supposed to.
How do I apply the OUTLINE section to the HTML element?
All SVG text effect tutorials imply that the text is inside the SVG element, but I need to apply this text stroke via the SVG filter to text in an HTML element.
<svg width="900" height="200" viewBox="100 0 900 200">
<filter id="outline">
<feMorphology in="SourceAlpha" result="DILATED" operator="dilate" radius="4"></feMorphology>
<feFlood flood-color="#32DFEC" flood-opacity="1" result="PINK"></feFlood>
<feComposite in="PINK" in2="DILATED" operator="in" result="OUTLINE"></feComposite>
<feMerge>
<feMergeNode in="OUTLINE" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<!-- DILATED TEXT -->
<text font-size="85px" dx="125" dy="130" font-weight="700" filter="url(#outline)">upgrade yourself</text>
</svg>
You just apply the filter to the HTML text in the same way...
p {
font-size: 85px;
font-weight: 700;
filter: url(#outline);
}
<svg width="0" height="0">
<filter id="outline">
<feMorphology in="SourceAlpha" result="DILATED" operator="dilate" radius="4"></feMorphology>
<feFlood flood-color="#32DFEC" flood-opacity="1" result="PINK"></feFlood>
<feComposite in="PINK" in2="DILATED" operator="in" result="OUTLINE"></feComposite>
<feMerge>
<feMergeNode in="OUTLINE" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</svg>
<p>upgrade yourself</p>
I am trying to create some ornate page dividers using SVGs with a fill pattern using the same image as the containing element's background image but I am having difficulty getting the SVG pattern to match the repeated background image of the containing element. I found a few similar questions on StackOverflow which mentioned using preserveAspectRatio but none of the solutions I've found are creating the desired effect.
Here's what my SVG code looks like:
<svg id="Layer_1" class="divider" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 150" >
<defs>
<pattern id="imgpattern" patternUnits="userSpaceOnUse" width="576" height="576" preserveAspectRatio="xMinYMin slice">
<image width="576" height="576" xlink:href="http://s12.postimg.org/730a258rx/pattern2.jpg"/>
</pattern>
<filter id="dropshadow" height="130%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="2" result="offsetblur"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path d="M-394.09,367.9V295.34l1400,0v70s-3.39.9-4.92,1.38c-56.68,17.79-114.85,25.72-174.22,26.17-36.9.27-73.6-2.7-110.25-6.28q-67.4-6.59-134.7-14.08c-49.65-5.51-99.28-8.74-149-1.64-35.12,5-68.54,15.05-99.24,33.08-6,3.53-12.09,7-18.13,10.48-8.94,5.18-17.93,5.51-27,.36-3.47-2-7.14-3.6-10.51-5.71-48.22-30.22-101-43.79-157.83-41.84-29.13,1-58.27,2.45-87.3,4.94-40.49,3.48-80.88,8.18-121.32,12.27-24.37,2.46-48.71,5.26-73.14,7a714.52,714.52,0,0,1-96.42.34,605.73,605.73,0,0,1-96.81-13.9C-368.07,374.88-394.09,367.9-394.09,367.9Z" transform="translate(394.09 -295.32)" stroke="none" fill="url(#imgpattern)" filter="url(#dropshadow)" />
</svg>
And here's a JSFiddle which recreates my issue. Notice how the background pattern of the SVG appears more stretched and because of that does not completely match the repeated background image of the container.
One option is just to move the pattern fill into the filter like so - although there is a small problem that your texture has a one pixel black border, so the tiling isn't perfect.
<filter id="dropshadowandfill" height="130%" >
<feImage x="0" y="0" width="575" height="575" xlink:href="http://s12.postimg.org/730a258rx/pattern2.jpg"></feImage>
<feTile/>
<feComposite operator="in" in2="SourceGraphic" result="filledOriginal"/>
<feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
<feOffset dx="0" dy="2" result="offsetblur"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="filledOriginal"/>
</feMerge>
</filter>
</defs>
<path d="M-394.09,367.9V295.34l1400,0v70s-3.39.9-4.92,1.38c-56.68,17.79-114.85,25.72-174.22,26.17-36.9.27-73.6-2.7-110.25-6.28q-67.4-6.59-134.7-14.08c-49.65-5.51-99.28-8.74-149-1.64-35.12,5-68.54,15.05-99.24,33.08-6,3.53-12.09,7-18.13,10.48-8.94,5.18-17.93,5.51-27,.36-3.47-2-7.14-3.6-10.51-5.71-48.22-30.22-101-43.79-157.83-41.84-29.13,1-58.27,2.45-87.3,4.94-40.49,3.48-80.88,8.18-121.32,12.27-24.37,2.46-48.71,5.26-73.14,7a714.52,714.52,0,0,1-96.42.34,605.73,605.73,0,0,1-96.81-13.9C-368.07,374.88-394.09,367.9-394.09,367.9Z" transform="translate(394.09 -295.32)" stroke="none" filter="url(#dropshadowandfill)" />
There is a filter
<filter id="filter">
<feGaussianBlur stdDeviation="4">
<feColorMatrix type="matrix" values="">
</filter>
applied to image
<image filter="url('#filter')">
I have a certain shape:
<polygon points="">
How can I use the polygon as a mask where the filter is not applied?
You could also apply the filter to the polygon and then use feImage to import your image into the filter. Using feComposite "in" will do the masking.
<svg height="210" width="500">
<defs>
<filter id="cutout" x="-300%" y="-300%" height="700%" width="700%">
<feImage result="photo" xlink:href="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/%D0%9D%D1%96%D0%B6%D0%BD%D0%B8%D0%B9_%D1%80%D0%B0%D0%BD%D0%BA%D0%BE%D0%B2%D0%B8%D0%B9_%D1%81%D0%B2%D1%96%D1%82%D0%BB%D0%BE.jpg/1280px-%D0%9D%D1%96%D0%B6%D0%BD%D0%B8%D0%B9_%D1%80%D0%B0%D0%BD%D0%BA%D0%BE%D0%B2%D0%B8%D0%B9_%D1%81%D0%B2%D1%96%D1%82%D0%BB%D0%BE.jpg" preserveAspectRatio="xMidYMid meet"/>
<feGaussianBlur stdDeviation="10" result="blurphoto"/>
<feComposite operator="in" in="photo" in2="SourceGraphic" result="photomask"/>
<feComposite operator="over" in2="blurphoto" in="photomask"/>
</filter>
</defs>
<polygon filter="url(#cutout)" points="20,10 250,190 200,30 160,34 160,210" style="fill:lime;stroke:purple;stroke-width:1" />
</svg>
Use two <image> elements at the same location.
The first image would have a filter (as you have it now).
The second image would not have a filter, instead it would have a clip.
The clipPath used by the second image will need to have the polygon as its contents.
If you really want one image, you could probably merge the images using canvas drawImage and then write out the composite image to a new <image> element.
I want to write a simple rectangle with a red shadow in SVG.
I have a simple filter:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1012" height="400">
<title>svg arrow with dropshadow</title>
<desc>An svg example of an arrow shape with a dropshadow filter applied. The dropshadow filter effect uses feGaussianBlur, feOffset and feMerge.</desc>
<defs>
<filter id="dropshadow" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feComponentTransfer in="SourceAlpha">
<feFuncR type="discrete" tableValues="1"/>
<feFuncG type="discrete" tableValues="0"/>
<feFuncB type="discrete" tableValues="0"/>
</feComponentTransfer>
<feGaussianBlur stdDeviation="2"/>
<feOffset dx="0" dy="0" result="shadow"/>
<feComposite in="SourceGraphic" in2="shadow" operator="over"/>
</filter>
</defs>
<rect rx="2" ry="2" fill="rgb(255,255,255)" x="5.25" y="5.25" width="141" height="50" fill-opacity="0.85" filter="url(#dropshadow)">
</svg>
Why in this example shadow color is not red? Where is my bad?
For those looking for a general solution, this worked for me inside a element:
<feGaussianBlur in="SourceAlpha" stdDeviation="1.7" result="blur"/>
<feOffset in="blur" dx="3" dy="3" result="offsetBlur"/>
<feFlood flood-color="#3D4574" flood-opacity="0.5" result="offsetColor"/>
<feComposite in="offsetColor" in2="offsetBlur" operator="in" result="offsetBlur"/>
You have provided invalid SVG - you need to close your <rect> element.
Your example (fixed) shows a red shadow for me in Chrome. Here's what this URL looks like for me with Chrome v15:
What OS/browser/version are you seeing different results with?
Edit: In Firefox v7 I see all greyscale, and in Safari v5 I don't see the shadow effect at all. Your answer, most likely then, is simply that you're testing in a browser/version with incomplete support of the SVG filter specification.