I needed to add a radial / conical gradient into an SVG circle. Unfortunately, there is no support for that on the standard: https://wiki.inkscape.org/wiki/index.php/Advanced_Gradients#Conical_gradient
So, I went for a solution similar to this: https://stackoverflow.com/a/18210763 but instead of using multiple colors, I use the same color with an alpha variation.
Mi final result ended like this:
<g fill="none" stroke-width="8" transform="translate(-49,-10) scale(1.2) rotate(0, 125, 50)" opacity="1">
<path d="M127.5593032836914,78.30342873930931 C124.73236846923828,78.30342873930931 122.4406967163086,76.50826272368431 122.4406967163086,74.29380044341087 C122.4406967163086,72.07933816313744 124.73236846923828,70.28415688872337 127.5593032836914,70.28415688872337 V78.30342873930931 z" fill="#23B26D"
transform="scale(-1,1) translate(-252,-48.7)" />
<path d="M124.99998474121094,25.63152313232422 A24.357080459594727,24.368465423583984 0 0 1 146.0932159423828,37.81575393676758 "
stroke="url(#redyel)" />
<path d="M146.0932159423828,37.81575393676758 A24.357080459594727,24.368465423583984 0 0 1 146.0932159423828,62.18423271179199 "
stroke="url(#yelgre)" />
<path d="M146.0932159423828,62.18423271179199 A24.357080459594727,24.368465423583984 0 0 1 124.99998474121094,74.36847496032715 "
stroke="url(#grecya)" />
<path d="M124.99998474121094,74.36847496032715 A24.357080459594727,24.368465423583984 0 0 1 103.90676879882812,62.18423271179199 "
stroke="url(#cyablu)" />
<path d="M103.90676879882812,62.18423271179199 A24.357080459594727,24.368465423583984 0 0 1 103.90676879882812,37.81575393676758 "
stroke="url(#blumag)" />
<path d="M103.90676879882812,37.81575393676758 A24.357080459594727,24.368465423583984 0 0 1 124.99998474121094,25.63152313232422 "
stroke="url(#magred)" />
</g>
<defs>
<linearGradient id="redyel" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#23B26D" stop-opacity="0.3"/>
<stop offset="100%" stop-color="#23B26D" stop-opacity="0.41"/>
</linearGradient>
<linearGradient id="yelgre" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0"
y2="1">
<stop offset="0%" stop-color="#23B26D" stop-opacity="0.41"/>
<stop offset="100%" stop-color="#23B26D" stop-opacity="0.52"/>
</linearGradient>
<linearGradient id="grecya" gradientUnits="objectBoundingBox" x1="1" y1="0" x2="0"
y2="1">
<stop offset="0%" stop-color="#23B26D" stop-opacity="0.52"/>
<stop offset="100%" stop-color="#23B26D" stop-opacity="0.63"/>
</linearGradient>
<linearGradient id="cyablu" gradientUnits="objectBoundingBox" x1="1" y1="1" x2="0"
y2="0">
<stop offset="0%" stop-color="#23B26D" stop-opacity="0.63"/>
<stop offset="100%" stop-color="#23B26D" stop-opacity="0.74"/>
</linearGradient>
<linearGradient id="blumag" gradientUnits="objectBoundingBox" x1="0" y1="1" x2="0"
y2="0">
<stop offset="0%" stop-color="#23B26D" stop-opacity="0.74"/>
<stop offset="100%" stop-color="#23B26D" stop-opacity="0.85"/>
</linearGradient>
<linearGradient id="magred" gradientUnits="objectBoundingBox" x1="0" y1="1" x2="1"
y2="0">
<stop offset="0%" stop-color="#23B26D" stop-opacity="0.85"/>
<stop offset="100%" stop-color="#23B26D" stop-opacity="1"/>
</linearGradient>
<linearGradient id="lgrad" x1="100%" y1="50%" x2="0%" y2="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:0"/>
<stop offset="60%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
</linearGradient>
<linearGradient id="rgrad" x1="0%" y1="50%" x2="100%" y2="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:0"/>
<stop offset="60%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,255,255);stop-opacity:1"/>
</linearGradient>
</defs>
https://codepen.io/scvsoft-marianovicente/pen/abmrdXo
It looks good enough, but now, I have small spaces between each element. (Depending on the browser in some places looks more visible than others).
I tried to apply a distortion/blur. to hide that but affects all borders.
It is possible to hide this spaces?
Try an annealing filter (dilate/erode). See if it solves your issues.
<svg class="streak-animation" viewbox="0 0 250 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="anneal">
<feMorphology operator="dilate" radius="1" />
<feMorphology operator="erode" radius="1" />
</filter>
</defs>
<g class="all-streaks" filter="url(#anneal)">
More details - as requested:
The feMorphology filter replaces every pixel's R,G,B and A values with the maximum (dilate) or minimum (erode) value of those color channels in a 2*radius. For simple monochrome shapes, this effectively adds (or subtracts) a one pixel outline around the shape.
In this case, the dilate fills in the super thin lines between shapes (and adds a 1px border around the whole shape). But then when you do an erode, there is no longer any semi-transparent pixels between the shapes to supply a low alpha value to erode, so only the 1px outline around the whole shape is removed.
I have a logo I created in Illustrator that I'm manually crafting into an SVG file piece by piece. It's a highly detailed illustration with lots of layering and blending so I have a lot of repeated gradients that only differ in the values of the gradientTransform property.
Here's an example
<radialGradient id="sil_bor_clr_layer_01" cx="145.8111" cy="91.9766" r="5.5753" gradientTransform="matrix(1.665142e-02 -0.9999 1.0812 1.800584e-02 43.939 236.1114)" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.6007" style="stop-color:#DBE2E8"/>
<stop offset="1" style="stop-color:#C0CDD8"/>
</radialGradient>
<radialGradient id="sil_bor_clr_layer_02" cx="121.087" cy="94.1915" r="6.7356" gradientTransform="matrix(-0.1704 -0.9854 0.917 -0.1586 55.3406 228.4433)" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.6007" style="stop-color:#DBE2E8"/>
<stop offset="1" style="stop-color:#C0CDD8"/>
</radialGradient>
<radialGradient id="sil_bor_clr_layer_03" cx="98.1764" cy="102.6783" r="7.6206" gradientTransform="matrix(-0.5989 -0.8008 0.6381 -0.4771 91.458 230.294)" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="0.6007" style="stop-color:#DBE2E8"/>
<stop offset="1" style="stop-color:#C0CDD8"/>
</radialGradient>
I have another 21 elements that use this same gradient which means I'll have to define it 21 more times just for the sake of defining the gradientTransform property.
Is there a way for me to define the gradientTransform on the SVG elements using the gradient so I can just define them once? These particular elements have a color layer, shadow layer and highlight layer which will be about 60+ instances of the same thing which is pretty ridiculous. I'm currently doing this in Angular so I know I could make components and export a few const to take care of this, but I'd prefer to keep it svg and css if possible.
You can use the href property to reference a template gradient.
If you want to support Safari you'll need to use xlink:href as Safari doesn't yet support bare href.
head, body, svg {
width: 100%;
height: 100%;
}
<svg viewBox="0 0 400 400">
<defs>
<radialGradient id="template">
<stop offset="10%" stop-color="gold"/>
<stop offset="95%" stop-color="green"/>
</radialGradient>
<radialGradient id="gradient1" gradientTransform="translate(0.25, 0.25) scale(0.5)" href="#template"/>
</defs>
<circle fill="url(#template)" cx="60" cy="60" r="50"/>
<circle fill="url(#gradient1)" cx="160" cy="60" r="50"/>
</svg>
If your gradient is supposed to look the same on each shape though, you'd be better off having one gradient and using objectBoundingBox units instead of userSpaceOnUse units.
I've got an SVG path which animates drawing out a word. After the animation is finished, the letters should begin to drip downward as though the text had been written in paint. The only solution I've come up with is to do it as a gif.
Is it possible to manipulate the path of the SVG after its drawn to create the effect?
<svg version="1.1" id="Layer_3" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-510.061 200.082 424.13 251.322" style="enable-background:new -510.061 200.082 424.13 251.322;" xml:space="preserve" preserveAspectRatio="xMidYMid meet">
<path class="path" fill="#FFFFFF" stroke="url(#g)" stroke-width="14" stroke-miterlimit="4" d="M-452.825,292.283
c-38.797-6.45-55.673,31.665-54.141,39.691c0.623,3.262,1.864,2.683,6.84,2.886c3.018,0.123,12.397-2.326,16.621-5.22
c9.716-6.655,13.538-11.867,13.538-11.867c1.06-1.231,2.76-1.456,4.78-1.316c1.963,0.136,15.194,26.35,15.847,27.428
c12.207,20.147,9.337,62.703,8.847,65.677c-3.361,20.419-33.532,55.715-42.439,29.547c-26.299-77.26,38.171-82.38,44.621-80.93
c13.822,3.106,12.376-10.28,11.743-13.3c-1.432-6.83-2.462-9.788-4.061-13.002c-4.008-8.06-8.904-16.999-8.176-17.467
c0.609-0.391-1.198,9.376,3.546,8.939c5.93-0.547,2.76-11.961,10.312-17.145c8.707-5.976,12.009-7.347,11.635-6.931
c-4.204,4.679-18.594,13.802-19.442,18.848c-1.09,6.479-1.73,27.306,13.344,32.355c6.558,2.197,35.442-58.24,37.348-68.115
c1.724-8.93-0.305-10.748-0.858-11.172c-2.443-1.871-6.648,0.054-7.167,0.292c-7.02,3.215-10.192,8.651-10.74,10.289
c-2.197,6.558-3.699,15.481,1.89,18.896c5.971,3.649,9.229,4.618,15.819-9.204c2.064-4.329,4.088-11.676,4.114-13.368
c0.07-4.595,1.431-4.653,2.944-0.539c8.273,22.494,16.686,19.444,30.462,34.976c5.15,5.807,21.282,23.499,31.24,63.769
c0.928,3.752-6.903,6.553-8.139,2.891c-8.315-24.633-10.271-34.758-15.895-50.381c-15.16-42.111-1.753-13.414-28.475-71.059
c1.661-1.142,6.421-3.193,11.871-4.381c5.702-1.242,14.565-1.38,15.939,5.132c1.989,9.427-12.222,18.347-15.609,28.852
c-6.35,19.69,0.48,32.902,5.927,29.905c34.808-19.149,27.865-13.051,31.663-20.621c1.556-3.102,0.943-9.097,0.931-12.031
c-0.061-14.49-19.911-58.049-21.116-57.597c-1.317,0.494,21.932,65.597,25.712,64.607c2.049-0.537-9.917-16.161-6.63-26.456
c0.884-2.767,1.444-7.339,8.422-7.099c19.793,0.683,20.382,29.092,24.906,34.772c2.265,2.843,9.185-24.448-3.663-60.94
c16.114,37.598,13.059,48.655,12.918,47.193c-3.072-31.917,1.788-49.326,20.006-50.841c9.18-0.764,16.58-1.225,16.58-1.225
s-35.881,3.339-36.249,17.898c-0.16,6.348,6.265,16.546,12.222,17.616c13.478,2.42,31.955-14.112,39.648-39.058
c2.094-6.789,22.84-20.669,23.074-20.388c0.415,0.498-49.858,35.959,7.977,20.739c32.55-8.566,25.661,19.843-8.652,30.146
c-29.735,8.929-31.283,17.326-71.967,30.749c-70.138,23.141-90.571,28.35-126.316,46.254c-40.064,20.067-60.502,35.66-60.502,35.66
s228.985-125.861,373.43-146.017"/>
<linearGradient id="g">
<stop offset="0.10" stop-color="#0ef1ff"/>
<stop offset="0.15" stop-color="#37c8ff"/>
<stop offset="0.20" stop-color="#58a7ff"/>
<stop offset="0.25" stop-color="#7a85ff"/>
<stop offset="0.30" stop-color="#ac53ff"/>
<stop offset="0.35" stop-color="#d22dff"/>
<stop offset="0.40" stop-color="#f20dff"/>
<stop offset="0.45" stop-color="#fe4cb8"/>
<stop offset="0.50" stop-color="#fe7394"/>
<stop offset="0.55" stop-color="#fd9376"/>
<stop offset="0.60" stop-color="#fdb05b"/>
<stop offset="0.65" stop-color="#fccf3e"/>
<stop offset="0.70" stop-color="#faec21"/>
<stop offset="0.75" stop-color="#d4c81c"/>
<stop offset="0.80" stop-color="#a49b15"/>
<stop offset="0.85" stop-color="#7d7610"/>
<stop offset="0.90" stop-color="#57520b"/>
<stop offset="0.95" stop-color="#353207"/>
<stop offset="1" stop-color="#000000"/>
</linearGradient>
</svg>
You can render the SVG to a Canvas (at runtime) and then do pixel manipulation.
Drawing an SVG file on a HTML5 canvas
An alternative approach would be to include "dripping paint" graphic elements in your SVG that are hidden initially, but are then revealed by changing their opacity, or animating the drip shapes.
Is it possible to achieve this gradient without having to define it first under <defs>?
I'm working on a network map showing network load on links between devices (switches, routers ..). I draw this using SVG, but I don't want to define all gradients as the start (uplink) and end (downlink) color is already given to me from the back end system and accessible through template variables in our application.
I wish to use inline-styles as it is much easier to do code wise as I don't have to keep track of thousands of link references and make sure I specify the right gradient for every link, as every gradient will '99.9%' of the time be unique for every line (link-load) I draw in my network map
Put in simple words, can I do something along the line: <line stroke=<linearGradient... ? without having to define one and reference back to it? Like style in CSS: <span style='color: blue'> .. </span>
<svg width="1024" height="800">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#000066;stop-opacity:1" />
<stop offset="50%" style="stop-color:#000066;stop-opacity:1" />
<stop offset="51%" style="stop-color:#00ffff;stop-opacity:1" />
<stop offset="100%" style="stop-color:#00ffff;stop-opacity:1" />
</linearGradient>
</defs>
<text x="50" y="50" fill="red">foo bar</text>a
<line stroke="url(#grad1)" x1="130.8757632890282"
y1="163.6818288670081" x2="651.9483366457684" y2="415.704113030817" />
</svg>
( http://jsfiddle.net/GgJnB/ )
You could use a data URI i.e. fill="url(data:image/svg+xml;base64,...encoded full svg...#mygradient)"
Here's an example: http://xn--dahlstrm-t4a.net/svg/paint/datauri-gradient.svg
First of all, I probably should have thought of this before asking the question at all, but my excuse is that I'm still learning svg. And my suggested answer is probably not the fully correct either. See code example at bottom with SVG Params which probably is the best solution and not having to keep track of a changing link reference to a gradient.
I however solved my issue with wrapping the following code inside a <g> for every link/line I draw as shown below:
<linearGradient id="gradientForLoopi" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#000066;stop-opacity:1" />
<stop offset="50%" style="stop-color:#000066;stop-opacity:1" />
<stop offset="51%" style="stop-color:#00ffff;stop-opacity:1" />
<stop offset="100%" style="stop-color:#00ffff;stop-opacity:1" />
</linearGradient>
<line stroke="url(#gradientForLoopi)" x1="130.8757632890282"
y1="163.6818288670081" x2="651.9483366457684" y2="415.704113030817" />
(I probably didn't even need to do that either, but I did for the semantic purposes so I could work with d3js more easily).
Doing some more research on the field, a better solution would be to use SVG Params (draft as pr. writing) when it is commonly available in browsers with HTML5 doctype (only partly working with SVG context headers(?), and not inline <svg> inside a HTML5 document) See demo with HTML5 doctype not working, and the same <svg>-content with svg content-type/.svg working as it should here.
You can probably already now use the SVG Params draft using a prototyping script, which I didn't get to work and probably doesn't work in 'all common browsers'-yet.
With SVG Params you would simply do something along the lines (I assume):
<defs>
<linearGradient id="linkload" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:param(uplink_color);stop-opacity:1" />
<stop offset="50%" style="stop-color:param(uplink_color);stop-opacity:1" />
<stop offset="51%" style="stop-color:param(downlink_color);stop-opacity:1" />
<stop offset="100%" style="stop-color:param(downlink_color);stop-opacity:1" />
</linearGradient>
<line stroke="url(#linkload)" x1="param(x1)"
y1="param(y1)" x2="param(x2)" y2="param(y2)" />
</defs>
<use id="linkid" xlink:href="#linkload" x1="300" x2="0" y1="0" y2="300">
<param name="downlink_color" value="#00ffff" />
<param name="uplink_color" value="#006666" />
</use>
<use id="linkid" .. for every link..
I've been reading the SVG specification and trying to find out whether you can have a combined fill and opacity gradient, but with the fill and opacity at different angles?
See the following example:
<linearGradient id="MyFill" gradientUnits="objectBoundingBox">
<stop offset="0%" stop-color="#FF0000" />
<stop offset="100%" stop-color="#0000FF" />
</linearGradient>
<linearGradient id="MyTransparency" gradientUnits="objectBoundingBox">
<stop offset="0%" stop-opacity="0%" x1="50%" x2="50%" />
<stop offset="100%" stop-opacity="100%" x1="50%" x2="50%" />
</linearGradient>
The opacity is defined at a different angle to the fill, how can I combine these into one fill? Or if I can't, how can I apply this to a single object?
It's not supported in SVG 1.1, but you can probably do a workaround with e.g filter markup to combine the gradients (an example), or <use> to apply different gradients to the same element that way, or write a script to do the color interpolation yourself.