Manipulate mid-points of SVG path after animation - svg
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.
Related
SVG gradient gradient units vs gradienttransform - not the same gradient
I am trying to figure out conversion from gradienttransform to gradientunits. I am getting different gradient distribution. Why? <svg width="540" height="540" xmlns="http://www.w3.org/2000/svg" > <defs> <linearGradient id="linear1" gradientTransform="rotate(45 0.5 0.5)" spreadMethod="pad"> <stop offset="0%" stop-color="gold"/> <stop offset="100%" stop-color="blue"/> </linearGradient> <linearGradient id="linear2" x1="0%" y1="0%" x2="100%" y2="100%" spreadMethod="pad"> <stop offset="0%" stop-color="gold"/> <stop offset="100%" stop-color="blue"/> </linearGradient> </defs> <rect fill="url(#linear1)" x="0" y="0" width="270" height="270" /> <rect fill="url(#linear2)" x="0" y="270" width="270" height="270" /> </svg> These 2 gradients are not the same:
because the distance between the left side and right side of a rectangle does not equal the distance from one corner to the opposite corner when you rotate it 45 degrees. the left and right sides are 270 units apart (default x2 is 100% the others default to 0%). the corners 270 * √2 units apart So the distance between x1,y1 and x2,y2 is different in each case given that the rotation transform is distance invariant.
SVG radial gradient has small spaces between elements
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 need help minimizing instances of SVG gradients
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.
How to make a vertical cross browser linear gradient using svg (for modern browsers)?
I am having trouble making SVG vertical linear gradients work in IE 11 , so the question is - given the following svg how to make the gradient identified as Gradient1 work in such a way that it is a vertical gradient? <?xml version="1.0" encoding="utf-8"?> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 79.4 59.5" xml:space="preserve"> <rect x="2.4" y="29.8" width="74.6" height="27.4"/> <g> <defs> <linearGradient id="Gradient1" gradientUnits="userSpaceOnUse" x1="100%" y1="0%" x2="100%" y2="100%" gradientTransform="rotate(45 50 50)"> <stop offset="0%" style="stop-color:#9AAFCC"/> <stop offset="20%" style="stop-color:#557096"/> <stop offset="35%" style="stop-color:#36557D"/> <stop offset="49%" style="stop-color:#1E3F6B"/> <stop offset="63%" style="stop-color:#0D305D"/> <stop offset="87%" style="stop-color:#032756"/> <stop offset="100%" style="stop-color:#002453"/> </linearGradient> </defs> <rect x="2.4" y="2.4" class="st0" width="74.6" height="27.4" fill="url(#Gradient1)"/> </g> </svg> I have of course tried to use a gradientTransform, what I have that works in Chrome (and presumably other browsers but not in IE) includes the following on the linearGradient element x1="-383.9706" y1="317.1023" x2="-382.9706" y2="317.1023" gradientTransform="matrix(0 -27.3826 -27.3826 0 8722.7842 -10484.3682)" however as soon as I try to do this in IE the gradient I have stops working and the rectangle just takes the first full stop color. I am open to translating the gradient into CSS if it can be made to work in the svg if that is the only cross-browser solution available.
Your example works the same in Chrome and IE for me. <svg viewBox="0 0 79.4 59.5"> <rect x="2.4" y="29.8" width="74.6" height="27.4"/> <defs> <linearGradient id="Gradient1" gradientUnits="userSpaceOnUse" x1="100%" y1="0%" x2="100%" y2="100%" gradientTransform="rotate(45 50 50)"> <stop offset="0%" style="stop-color:#9AAFCC"/> <stop offset="20%" style="stop-color:#557096"/> <stop offset="35%" style="stop-color:#36557D"/> <stop offset="49%" style="stop-color:#1E3F6B"/> <stop offset="63%" style="stop-color:#0D305D"/> <stop offset="87%" style="stop-color:#032756"/> <stop offset="100%" style="stop-color:#002453"/> </linearGradient> </defs> <rect x="2.4" y="2.4" class="st0" width="74.6" height="27.4" fill="url(#Gradient1)"/> </svg> It's a linear gradient rotated 45 degrees as your markup requests. If you want the gradient to be vertical, remove the gradientTransform. <svg viewBox="0 0 79.4 59.5"> <rect x="2.4" y="29.8" width="74.6" height="27.4"/> <defs> <linearGradient id="Gradient1" gradientUnits="userSpaceOnUse" x1="100%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" style="stop-color:#9AAFCC"/> <stop offset="20%" style="stop-color:#557096"/> <stop offset="35%" style="stop-color:#36557D"/> <stop offset="49%" style="stop-color:#1E3F6B"/> <stop offset="63%" style="stop-color:#0D305D"/> <stop offset="87%" style="stop-color:#032756"/> <stop offset="100%" style="stop-color:#002453"/> </linearGradient> </defs> <rect x="2.4" y="2.4" class="st0" width="74.6" height="27.4" fill="url(#Gradient1)"/> </svg>
SVG linear gradient from hue 0 to 360
(source: elv1s.ru) What a proper way to do a gradient like this? I tried this SVG: <linearGradient id="hue" x1="0" y1="1" x2="0" y2="0"> <stop offset="0%" stop-color="#ff0000"/> <stop offset="17%" stop-color="#ffff00"/> <stop offset="34%" stop-color="#00ff00"/> <stop offset="50%" stop-color="#00ffff"/> <stop offset="66%" stop-color="#0000ff"/> <stop offset="82%" stop-color="#ff00ff"/> <stop offset="100%" stop-color="#ff0000"/> </linearGradient> It works, but still not good enough: (source: elv1s.ru) I can see the difference between those two gradients. Is there a better way of doing it?
Have you tried using better precision in your %? As Josh is showing, you can have sub-percent precision and space your stops better.
If it's acceptable to generate the SVG with Javascript you might want to look at: How to interpolate hue values in HSV colour space? or perhaps: http://www.carto.net/papers/svg/gui/colourPicker/ Edit: Actually there is one here. would that be correct? http://upload.wikimedia.org/wikipedia/commons/5/5d/HSV-RGB-comparison.svg
<linearGradient id="linearGradient3706"> <stop style="stop-color:#ff1c1c;stop-opacity:1;" offset="0" id="stop3708" /> <stop id="stop3728" offset="0.16105497" style="stop-color:#fd00ca;stop-opacity:1;" /> <stop id="stop3724" offset="0.35173747" style="stop-color:#0202ff;stop-opacity:1;" /> <stop id="stop3720" offset="0.48789391" style="stop-color:#02fff9;stop-opacity:1;" /> <stop id="stop3718" offset="0.70091939" style="stop-color:#60ff18;stop-opacity:1;" /> <stop id="stop3714" offset="0.83720928" style="stop-color:#ffef15;stop-opacity:1;" /> <stop style="stop-color:#ff0000;stop-opacity:1;" offset="1" id="stop3710" /> </linearGradient> works for me (made with inskape)