SVG arc with conical gradient [duplicate] - svg

Is there a way to do an 'angular gradient' in SVG?
(I don't know the official term -- it's the kind of gradient you see in color-pickers, where it varies by angle.)
SVG seems to support only linear and radial gradients, but I'm thinking there might be some way to use a transform to simulate what I want.
thanks!

...10 years later...
CSS now supports conical gradients, although browser support is mixed at the time of writing this.
You could apply a <clipPath /> to a <foreignObject /> whose contents use a CSS conical gradient to achieve the desired effect.
https://codepen.io/eastonium/pen/abOpdEm

There's no standard support to do angular (conical) gradients.
But see http://wiki.inkscape.org/wiki/index.php/Advanced_Gradients#Conical_gradient for some approximation methods (source code not included, though). Examples on that link do not work.

Here is how to do it using patterns: https://jsfiddle.net/prozoroff/8eodzrke/
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="800" width="800">
<defs>
<linearGradient id="Gradient1" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="#ff0000"/>
<stop offset="100%" stop-color="#00ff00"/>
</linearGradient>
<linearGradient id="Gradient2" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="#0000ff"/>
<stop offset="100%" stop-color="#00ff00"/>
</linearGradient>
<pattern id="Pattern" x="0" y="0" width="600" height="600" patternUnits="userSpaceOnUse">
<g transform="rotate(0, 300, 300)">
<rect shape-rendering="crispEdges" x="0" y="0" width="300" height="600" fill="url(#Gradient1)"/>
<rect shape-rendering="crispEdges" x="300" y="0" width="300" height="600" fill="url(#Gradient2)"/>
</g>
</pattern>
</defs>
<path id='arc5' style="stroke: url(#Pattern);" fill='transparent' stroke-width='60' d='M 364 58 A 250 250 0 1 1 235 58'/>
</svg>

In my answer to this similar question, I used six linear gradients to approximate a conical gradient. If you are only needing the gradient for the stroke/perimeter of a circle, rather than the fill, then it should be a good enough approximation.
svg multiple color on circle stroke

Here is a possible vector conical gradient, but only VML (+IE) can do it...:
http://midiwebconcept.free.fr/Demos/degradeconique.htm

If you dig into this page, you'll find code that approximates a conic gradient in SVG by drawing it as a series of 1 degree arcs.

Add a patern with 100% width and height so its just a one repetition pattern
<div style="width:100px">
<svg viewBox="0 0 35 35" style="transform: scale(1) rotate(-90deg)">
<defs>
<pattern
id="p1"
patternUnits="userSpaceOnUse"
width="100%"
height="100%"
patternTransform="rotate(90)"
>
<image href="https://blogs.igalia.com/dpino/files/2020/06/conic-gradient.png" width="36" height="36" />
</pattern>
</defs>
<g>
<circle
cx="50%"
cy="50%"
stroke-width="2"
r="15.915"
stroke-dasharray="89, 100"
stroke="url(#p1)"
fill="none"
/>
</g>
</svg>
</div>

http://en.wikipedia.org/wiki/File:Blended_colour_wheel.svg uses an innovative technique to approximate it.

Related

How can I make an SVG pattern vary its repetition count as container dimension varies?

I have got this test image that shows two rectangles filled with 16 circles each:
<svg width="500" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Gradient1">
<stop offset="5%" stop-color="white"/>
<stop offset="95%" stop-color="blue"/>
</linearGradient>
<pattern id="Pattern" x="0" y="0" width=".25" height=".25">
<rect x="0" y="0" width="50" height="50" fill="skyblue"/>
<circle cx="25" cy="25" r="20" fill="url(#Gradient1)" fill-opacity="0.5"/>
</pattern>
</defs>
<rect fill="url(#Pattern)" stroke="red" width="200" height="200"/>
<rect fill="url(#Pattern)" stroke="red" width="200" height="400" x="210"/>
</svg>
I would like the same pattern to neatly fill the two rectangles, without gaps between circles and without stretching of the circles. The rectangle at right has room for 32 circles, and I want to see them all in there, but instead there are 16 with gaps.
Is there any way to change the single pattern here so that it'll neatly fill one rectangle with 16 tiles and the other with 32? It seems like a very basic thing to want to do, but I've fussed with the many coordinate- and transformation-related parameters of the pattern for a while and found no way.
In this simple example it's easy enough to work around the problem by, say, making two patterns for the two rectangles instead of having them share one, and tweaking height for the tall rectangle's pattern. But in the real project where I want to use patterns, bounding boxes on pattern-filled shapes have unpredictable dimensions, and so I can't easily alter the tile dimensions to compensate for their variation... as far as I can tell, anyway.
Am I missing something? Or is the pattern system just not designed for this usage, simple and basic though it may seem? Maybe I should be using clip paths or masks or something to cut my tilings out of a big, easily controlled square instead of applying a pattern to each shape I want to tile??
Set patternUnits ="userSpaceOnUse" and replace the dimensions of the pattern parameters with absolute values.
For example: instead of width =".25" set width ="50px"
<svg width="500" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Gradient1">
<stop offset="5%" stop-color="white"/>
<stop offset="95%" stop-color="blue"/>
</linearGradient>
<pattern id="Pattern" x="0" y="0" width="50px" height="50px" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="50" height="50" fill="skyblue"/>
<circle cx="25" cy="25" r="20" fill="url(#Gradient1)" fill-opacity="0.5"/>
</pattern>
</defs>
<rect fill="url(#Pattern)" stroke="red" width="200" height="200"/>
<rect fill="url(#Pattern)" stroke="red" width="200" height="400" x="250"/>
</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>

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

SVG — radial gradient with a smooth edged cutout

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.

SVG angular gradient

Is there a way to do an 'angular gradient' in SVG?
(I don't know the official term -- it's the kind of gradient you see in color-pickers, where it varies by angle.)
SVG seems to support only linear and radial gradients, but I'm thinking there might be some way to use a transform to simulate what I want.
thanks!
...10 years later...
CSS now supports conical gradients, although browser support is mixed at the time of writing this.
You could apply a <clipPath /> to a <foreignObject /> whose contents use a CSS conical gradient to achieve the desired effect.
https://codepen.io/eastonium/pen/abOpdEm
There's no standard support to do angular (conical) gradients.
But see http://wiki.inkscape.org/wiki/index.php/Advanced_Gradients#Conical_gradient for some approximation methods (source code not included, though). Examples on that link do not work.
Here is how to do it using patterns: https://jsfiddle.net/prozoroff/8eodzrke/
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="800" width="800">
<defs>
<linearGradient id="Gradient1" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="#ff0000"/>
<stop offset="100%" stop-color="#00ff00"/>
</linearGradient>
<linearGradient id="Gradient2" gradientTransform="rotate(90)">
<stop offset="0%" stop-color="#0000ff"/>
<stop offset="100%" stop-color="#00ff00"/>
</linearGradient>
<pattern id="Pattern" x="0" y="0" width="600" height="600" patternUnits="userSpaceOnUse">
<g transform="rotate(0, 300, 300)">
<rect shape-rendering="crispEdges" x="0" y="0" width="300" height="600" fill="url(#Gradient1)"/>
<rect shape-rendering="crispEdges" x="300" y="0" width="300" height="600" fill="url(#Gradient2)"/>
</g>
</pattern>
</defs>
<path id='arc5' style="stroke: url(#Pattern);" fill='transparent' stroke-width='60' d='M 364 58 A 250 250 0 1 1 235 58'/>
</svg>
In my answer to this similar question, I used six linear gradients to approximate a conical gradient. If you are only needing the gradient for the stroke/perimeter of a circle, rather than the fill, then it should be a good enough approximation.
svg multiple color on circle stroke
Here is a possible vector conical gradient, but only VML (+IE) can do it...:
http://midiwebconcept.free.fr/Demos/degradeconique.htm
If you dig into this page, you'll find code that approximates a conic gradient in SVG by drawing it as a series of 1 degree arcs.
Add a patern with 100% width and height so its just a one repetition pattern
<div style="width:100px">
<svg viewBox="0 0 35 35" style="transform: scale(1) rotate(-90deg)">
<defs>
<pattern
id="p1"
patternUnits="userSpaceOnUse"
width="100%"
height="100%"
patternTransform="rotate(90)"
>
<image href="https://blogs.igalia.com/dpino/files/2020/06/conic-gradient.png" width="36" height="36" />
</pattern>
</defs>
<g>
<circle
cx="50%"
cy="50%"
stroke-width="2"
r="15.915"
stroke-dasharray="89, 100"
stroke="url(#p1)"
fill="none"
/>
</g>
</svg>
</div>
http://en.wikipedia.org/wiki/File:Blended_colour_wheel.svg uses an innovative technique to approximate it.

Resources