SVG — radial gradient with a smooth edged cutout - svg

I'm trying to create a SVG background image like this (two colors, radial gradient, S-shape cutout with smooth edges):
It's quite easy to create a radial gradient (e.g. using this tool):
<!-- SVG syntax -->
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">
<radialGradient id="g920" gradientUnits="userSpaceOnUse" cx="5.408560311284047%" cy="0%" r="93.04166277718278%">
<stop stop-color="#ed1c24" offset="0.1"/><stop stop-color="#003663" offset="1"/>
</radialGradient>
<rect x="-50" y="-50" width="101" height="101" fill="url(#g920)" />
</svg>
but is it possible to add the cutout too?

Lennis' answer was close. But you would get better results by combining the fill and the filter in one element, rather than try to use a blurry white shape to hide part of the gradient.
Note that the blur will affect any edge of the shape, including the top, left and right. So you need to make sure those edges are well away from (outside of) the edge of the SVG viewport.
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">
<defs>
<radialGradient id="g" gradientUnits="userSpaceOnUse" cx="5.4%" cy="0%" r="93%">
<stop stop-color="#ed1c24" offset="0.1"/>
<stop stop-color="#003663" offset="0.8"/>
</radialGradient>
<filter id="f1" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation=".05" />
</filter>
</defs>
<path id="svg_1" d="M -0.5,-0.5
L 1.5,-0.5
L 1.5,0.5
L 1,0.5
C 1,0 0.6,0.1 0.5,0.25
C 0.4,0.4 0.1,0.4 0,0.25
L -0.5,0.25
Z"
fill="url(#g)" filter="url(#f1)"/>
</svg>

You could use a blur on a white element to make it look like a cutout.
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">
<defs>
<radialGradient id="g" gradientUnits="userSpaceOnUse" cx="5.4%" cy="0%" r="93%">
<stop stop-color="#ed1c24" offset="0.1"/>
<stop stop-color="#003663" offset="1"/>
</radialGradient>
<filter id="f1" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation=".05" />
</filter>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="url(#g)" />
<path id="svg_1" fill="white" d="m-0.1,0.5 l0,0.55l1.15,0l0,-0.53495c0,0 -0.1,-0.1 -0.5,0c-0.3,0.1 -0.5,0 -0.5,0l-0.1,0z" filter="url(#f1)"/>
</svg>
You could also try a meshgradient, it's in the svg 2.0 spec. At the moment no browser supports it that I know off.

Related

How to have image inside svg background with radialGradient

I have svg element with some image inside it. I tried clipPath, but the results were not as expected
here's the code
<svg width="5396" height="829" enable-background="new" version="1.1" viewBox="0 0 1427.7 219.34" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="headera" cx="-334.2" cy="-79.465" r="713.85" gradientTransform="matrix(.35196 -.0011319 .0010719 .334 127.5 106)" gradientUnits="userSpaceOnUse">
<stop stop-color="#9d6173" offset="0"/>
<stop stop-color="#594b4f" offset="1"/>
</radialGradient>
<clipPath id="dodol">
<rect x="36.286" y="108.01" width="0" height="0" fill-opacity="0" stroke="#453030" stroke-linecap="round" stroke-linejoin="round" stroke-width=".052917"/>
<path d="m-535.38 77.813v6.0476c2.9078 113.15 92.911 174.65 152.71 167.82 169.93-23.912 248.91 44.042 387.75 45.474 56.339-1.17 204.04-22.034 204.04-22.034 78.053-5.4634 100.32 22.158 142.53 22.034 181.38-0.15553 205.7-119.12 449.25-127.14 104.33-1.7411 90.846-92.203 90.846-92.203z" fill="url(#headera)"/>
</clipPath>
</defs>
<g transform="matrix(1 0 0 .99999 535.38 -77.81)">
<rect x="36.286" y="108.01" width="0" height="0" fill-opacity="0" stroke="#453030" stroke-linecap="round" stroke-linejoin="round" stroke-width=".052917"/>
<path d="m-535.38 77.813v6.0476c2.9078 113.15 92.911 174.65 152.71 167.82 169.93-23.912 248.91 44.042 387.75 45.474 56.339-1.17 204.04-22.034 204.04-22.034 78.053-5.4634 100.32 22.158 142.53 22.034 181.38-0.15553 205.7-119.12 449.25-127.14 104.33-1.7411 90.846-92.203 90.846-92.203z" fill="url(#headera)"/>
</g>
<image clip-path="url(#dodol)" preserveAspectRatio="xMaxYMid meet" width="643px" height="50%" x="250" y="20" xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"/>
</svg>
the problem with the code is I can't resize the image as it should and some of the outgoing image that exceeds the svg element remains visible
what i want to achive is
the svg shape appears as the background for the image inside it
the image appereance clipped by svg shape
I can adjust the position and size of the image
thanks
I'm not very sure this is what you need. Please take a look.
The main idea is that you have to put the image inside the transformed group.
Also I've removed some useless elements (rects with width and height 0). Also instead of using the same path twice I'm reusing it with <use>
Yet another thing: I've changed the image size so that it keeps it's width/height ratio. It may not be what you want.
<svg viewBox="0 0 1427.7 219.34" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="headera" cx="-334.2" cy="-79.465" r="713.85" gradientTransform="matrix(.35196 -.0011319 .0010719 .334 127.5 106)" gradientUnits="userSpaceOnUse">
<stop stop-color="#9d6173" offset="0"/>
<stop stop-color="#594b4f" offset="1"/>
</radialGradient>
<clipPath id="dodol">
<path id="thePath" d="m-535.38 77.813v6.0476c2.9078 113.15 92.911 174.65 152.71 167.82 169.93-23.912 248.91 44.042 387.75 45.474 56.339-1.17 204.04-22.034 204.04-22.034 78.053-5.4634 100.32 22.158 142.53 22.034 181.38-0.15553 205.7-119.12 449.25-127.14 104.33-1.7411 90.846-92.203 90.846-92.203z" />
</clipPath>
</defs>
<g transform="matrix(1 0 0 .99999 535.38 -77.81)">
<use xlink:href="#thePath" fill="url(#headera)"/>
<image clip-path="url(#dodol)" width="600" height="529" x="250" y="20" xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"/>
</g>
</svg>

Pattern with three stripes

I'm new to svg (and design in general) and looking for a way to fill a svg shape/path with three equally-sized diagonal stripes in different colors. For two stripes, I already found a solution on Stack Overflow (Simple fill pattern in svg : diagonal hatching):
<svg width="300" height="30" viewBox="0 0 200 10">
<pattern id="diagonalHatch" width="15" height="10"
patternTransform="rotate(135 0 0)" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="100%" height="100%" fill="orange"></rect>
<line x1="0" y1="0" x2="0" y2="10" style="stroke:blue; stroke-
width:15" />
</pattern>
<rect x="0" y="0" width="100%" height="100%" fill="url(#diagonalHatch)"/>
</svg>
I modified the solution somewhat, including a rectangle for background color (is there a better way to do this?). But I just can't figure out how to do it for three stripes. Another thing I also wondered is whether there is a way to pass the colors as some kind of parameters to the pattern, so that there is no need to declare multiple patterns just for color switching?
I've added a second line to your pattern. Also I've removed the attributes with a value == 0. If your stroke-width is 10 (for example) you will need to begin your line at 5 since a line is drawn 5 units to one side and 5 to the other side. I hope it helps.
<svg width="300" height="300" viewBox="0 0 200 200">
<pattern id="diagonalHatch" width="30" height="10"
patternTransform="rotate(130)" patternUnits="userSpaceOnUse">
<rect width="100%" height="100%" fill="orange"></rect>
<line x1="5" x2="5" y2="10" style="stroke:blue; stroke-width:10" />
<line x1="15" x2="15" y2="10" style="stroke:red; stroke-width:10" />
</pattern>
<rect x="0" y="0" width="100%" height="100%" fill="url(#diagonalHatch)"/>
</svg>
Another approach is to create your stripes using a repeating linear gradient.
<svg width="300" height="300" viewBox="0 0 200 200">
<defs>
<linearGradient id="diagonalHatch" gradientUnits="userSpaceOnUse"
x2="30" spreadMethod="repeat" gradientTransform="rotate(-45)">
<stop offset="0" stop-color="orange"/>
<stop offset="0.33" stop-color="orange"/>
<stop offset="0.33" stop-color="blue"/>
<stop offset="0.67" stop-color="blue"/>
<stop offset="0.67" stop-color="red"/>
<stop offset="1.0" stop-color="red"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="url(#diagonalHatch)"/>
</svg>

Apply glow to SVG element with a gradient

I have an SVG element that's based on a circle and a mask to create a ring.
The code is as follows:
<svg width="100%" height="100%" viewBox="0 0 300 300" version="1.1">
<defs>
<linearGradient x1="97.3756325%" y1="100%" x2="0%" y2="100%" id="gradient">
<stop stop-color="#FF00AC" offset="0%"></stop>
<stop stop-color="#5D00C4" offset="100%"></stop>
</linearGradient>
<mask id="circle-mask">
<circle cx="150" cy="150" r="145" fill="white"/>
<circle cx="150" cy="150" r="140" fill="black"/>
</mask>
</defs>
<circle cx="150" cy="150" r="145" mask="url(#circle-mask)" fill="url(#gradient)"/>
</svg>
The ring got a gradient as fill color. Now I want to apply a glow effect on the ring that uses the colors of the gradient. Any ideas on how to do that?
What is a "glow"? I don't think there is a canonical definition, so I'm going with one that I have seen used before: a backdrop shadow that is colored and whose opacity values are exagerated. To define those effects, refer to the SVG <filter> spec, its support is pretty good across browsers.
I understand you need the mask for more complex situations than this one. The important thing here is the order in which different effects are applied: clip paths and masks are processed after filter effects:
First the element is styled under absence of filter effects, masking, clipping and opacity. Then the element and its descendants are drawn on a temporary canvas. In a last step the following effects are applied to the element in order: filter effects, clipping, masking and opacity.
Therefore you need to wrap the masked element in a <g> and apply the glow filter there.
Vary stdDeviation to stretch or shrink the shadow, and vary slope to change its opacity. If you set the slope to a value > 2, you will no longer get a clear border between the ring and its shadow.
<svg width="100%" height="100%" viewBox="0 0 300 300" version="1.1">
<defs>
<linearGradient x1="97.3756325%" y1="100%" x2="0%" y2="100%" id="gradient">
<stop stop-color="#FF00AC" offset="0%"></stop>
<stop stop-color="#5D00C4" offset="100%"></stop>
</linearGradient>
<mask id="circle-mask">
<circle cx="150" cy="150" r="145" fill="white"/>
<circle cx="150" cy="150" r="140" fill="black"/>
</mask>
<filter id="glow">
<feGaussianBlur stdDeviation="5"/>
<feComponentTransfer>
<feFuncA type="linear" slope="2" />
</feComponentTransfer>
<feBlend in2="SourceGraphic" />
</filter>
</defs>
<g filter="url(#glow)">
<circle cx="150" cy="150" r="145" mask="url(#circle-mask)" fill="url(#gradient)"/>
</g>
</svg>

How to achieve a Progressive Blur using SVG by combining a filter with a mask?

I'm trying to achieve a linear blur effect like the one on the image, but using just svg, no css!!!
Notice how the top of the image is completely blurred, but the bottom isn't.
In SVG Blur effect can be achieved using feGaussianBlur. The gradient can be used with linearGradient.
How can these two be combined?
While it's possible to do this entirely in a filter without using double images, the solution can be buggy because of how both Firefox and Chrome handle ops on low opacities. So this is an alternative & straightforward way to do it using doubled images. Note that you have to clip the image edges for a clean image because feGaussianBlur creates edge fades.
<svg width="800px" height="600px">
<defs>
<linearGradient id="progFade" x1="0%" x2="0%" y1="0%" y2="100%">
<stop offset="0%" stop-color="black"/>
<stop offset="60%" stop-color="white"/>
</linearGradient>
<mask id="progFadeMask" >
<rect x="0%" y="0%" width="100%" height="100%" fill="url(#progFade)" />
<mask>
<filter id="blurme" x="0%" y="0%" width="100%" height="100%">
<feGaussianBlur stdDeviation="15" result="blurry"/>
</filter>
<clipPath id="outerclip">
<rect x="20" y="20" width="460" height="380" fill="black">
</clipPath>
</defs>
<g clip-path="url(#outerclip)">
<image x="0" y="0" filter="url(#blurme)" xlink:href="http://cps-static.rovicorp.com/3/JPG_400/MI0003/890/MI0003890640.jpg" width="494" height="400"/>
<image x="0" y="0" mask="url(#progFadeMask)" xlink:href="http://cps-static.rovicorp.com/3/JPG_400/MI0003/890/MI0003890640.jpg" width="494" height="400"/>
</g>
</svg>
Enjoy Progressively Blurred Chaka Khan

Is it possible to apply a transform matrix to a SVG filter effect

I'm trying to recreate an iphone maps like push pin in SVG and I have the pin part down but I'm wondering how to tackle the shadow. I've seen a bunch of drop shadow examples but they're all just offsetting the original by a few pixels. Is it possible to apply a transform matrix to a filter so it's skewed?
Here's the pin SVG so far:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<radialGradient id="SVGID_1_" cx="29.3623" cy="31.1719" r="11.6241" gradientTransform="matrix(1.1875 0 0 1.1875 -30.8438 -30.2812)" gradientUnits="userSpaceOnUse">
<stop offset="0.2637" style="stop-color:#FF0000"/>
<stop offset="1" style="stop-color:#6D0000"/>
</radialGradient>
</defs>
<rect x="9.251" y="13.844" fill="#CCCCCC" stroke="#7C7C7C" width="2" height="24.83"/>
<circle fill="url(#SVGID_1_)" stroke="#660000" cx="10.5" cy="11.5" r="9.5"/>
<ellipse transform="matrix(0.8843 0.4669 -0.4669 0.8843 4.475 -1.6621)" fill="#FFCCCC" cx="6.591" cy="8.199" rx="1.538" ry="1.891"/>
</svg>
thanks!
Here is a simple transform and filter to rotate it. If you want to do the skewing too you will need to replace the rotate line with some matrix stuff.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs>
<radialGradient id="SVGID_1_" cx="29.3623" cy="31.1719" r="11.6241" gradientTransform="matrix(1.1875 0 0 1.1875 -30.8438 -30.2812)" gradientUnits="userSpaceOnUse">
<stop offset="0.2637" style="stop-color:#FF0000"/>
<stop offset="1" style="stop-color:#6D0000"/>
</radialGradient>
<filter id="drop-shadow">
<feGaussianBlur in="SourceAlpha" result="blur-out" stdDeviation="1" />
</filter>
</defs>
<g id="pin">
<rect x="9.251" y="13.844" fill="#CCCCCC" stroke="#7C7C7C" width="2" height="24.83"/>
<circle fill="url(#SVGID_1_)" stroke="#660000" cx="10.5" cy="11.5" r="9.5"/>
<ellipse transform="matrix(0.8843 0.4669 -0.4669 0.8843 4.475 -1.6621)" fill="#FFCCCC" cx="6.591" cy="8.199" rx="1.538" ry="1.891"/>
</g>
<use xlink:href="#pin" transform="rotate(60 10.251 38.674)" filter="url(#drop-shadow)"/>
</svg>

Resources