Animating Svg Fill Linearly Along Length of Path

Animating SVG fill linearly along length of path

You could do this (easier to describe than to do, there's a lot of fiddly work involved):

  1. Draw a smooth path on top of the shape that follows what you would consider the "path" and select such a stroke-width that the path covers the shape everywhere.
  2. I would leave the final dot completely out of this, as it is so much thicker than the rest.
  3. Divide the path in such a way that it has no overlapping parts. Order the parts in drawing order, make sure every partial path is drawn in the right direction.
  4. Now divide the shape in the same way, making sure each part is exactly beneath the path on top.
  5. Associate each of the shapes with one of the paths on top, defining the path as a mask for the shape. The path must have stroke:white. Preserve order.
  6. Now you can animate the paths that define the masks with a stroke-dashoffset animation.
  7. I would simply hide the final dot until the pseudo-line animation finishes and then reveal it at once.

Edit: I've definitely got too much time on my hands today, here's the working result:

.clef {    fill: black;    stroke: black;    stroke-width: 0.1;}mask path {    fill: none;    stroke: white;    stroke-width: 6;}#mask1 path {    stroke-dasharray: 100.8186 100.8186;    stroke-dashoffset: 100.8186;    animation: draw1 1s linear forwards;}@keyframes draw1 {    from { stroke-dashoffset: 100.8186; }    to { stroke-dashoffset: 0; }}#mask2 path {    stroke-dasharray: 83.6713 83.6713;    stroke-dashoffset: 83.6713;    animation: draw2 1s 1s linear forwards;}@keyframes draw2 {    from { stroke-dashoffset: 83.6713; }    to { stroke-dashoffset: 0; }}.dot {    opacity: 0;    animation: reveal 0s 2.5s forwards;}@keyframes reveal {    from { opacity: 0; }    to { opacity: 1; }}
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="200" viewBox="0 0 44 75">  <defs>  <mask id="mask1" maskUnits="userSpaceOnUse">      <path d="M 24.3018,49.658 C 15.0191,46.9092 18.5393,38.1126 25.6256,38.2163 35.5458,38.3614 34.8431,54.3874 22.6943,54.1023 12.0123,53.8516 7.34095,40.0402 18.4391,30.1787 29.5373,20.3173 29.9235,12.5622 27.8005,9.28112" />  </mask>  <mask id="mask2" maskUnits="userSpaceOnUse">      <path d="M 27.8005,9.28112 C 25.1382,5.16638 17.6602,8.86888 20.5194,22.1412 L 28.1788,57.6956 C 31.6264,73.699 16.4903,72.3627 15.035,62.329" />  </mask>  </defs>  <path class="clef" mask="url(#mask1)" d="M 26.8522,9.90048 C 26.912,9.95039 26.9649,10.0085 27.0101,10.075 27.4815,10.7683 28.6214,14.0098 25.3767,19.8157 22.846,24.3437 11.0718,30.2815 10.2077,40.9075 9.45969,50.1477 19.1325,56.9723 27.4811,54.2894 33.0239,52.5081 35.8812,44.0959 32.4504,39.7568 23.3964,28.3057 8.87616,45.8309 22.9422,50.6319 21.4126,49.4286 20.37,48.4968 20.1759,47.3578 18.286,36.2692 34.9591,39.1968 30.4666,49.7165 28.6194,54.0421 21.1577,54.879 16.9085,51.0198 13.3489,47.787 11.7693,41.5593 15.7305,37.0885 21.0956,31.0332 27.4302,25.5974 29.1125,17.3081 29.7841,13.9988 29.4887,10.9357 28.6445,8.70078 Z" />  <path class="clef" mask="url(#mask2)" d="M 15.7311,63.3465 C 15.3353,65.46 17.5402,69.8491 21.9764,69.9924 27.3392,70.1658 30.7655,66.0634 29.1692,59.3682 L 21.164,22.4229 C 20.2111,18.0249 20.9262,15.6394 21.4351,14.2178 22.7185,10.6326 25.8192,9.03863 26.8522,9.90048 L 28.6445,8.70078 C 26.9883,4.31578 23.2199,3.11893 20.4997,9.50576 19.1217,12.7412 18.6085,15.989 19.9279,22.2128 L 27.9268,59.9444 C 28.4995,62.6457 28.1161,66.3629 25.595,68.0714 24.3461,68.9177 19.9267,69.5001 18.8455,67.48" />  <path class="clef dot" d="M 15.6702,63.6634 A 3.77139,3.8362 1.075 0 1 19.5129,59.8986 3.77139,3.8362 1.075 0 1 23.2116,63.8049 3.77139,3.8362 1.075 0 1 19.3689,67.5697 3.77139,3.8362 1.075 0 1 15.6702,63.6634 Z" /></svg>

Issue animating SVG along a path

There isn't really a question as such (its doing what it should I believe), so not really a solution. But I will try and highlight what is happening, and where the confusion is. I think this is because the rotate="auto" and the x,y of the rect are being taken as combined transforms if you like as it animates along the path. If you change x,y to 0,0 it will highlight this.

To try and make it a bit clearer, I've combined a few rects with different x,y values. Its the same effect as if there was a transform being combined with the rotate.

You will see how the green one seems to reverse, its just that its further out when the rotate is happening.

http://jsfiddle.net/fcz69/4/ is a quick example to highlight whats happening.

The animationMotion element description can be found here http://www.w3.org/TR/SVG/animate.html#RotateAttribute its worth reading the bit on 'rotate' there, but it may take a while to get your head around it, if not used to matrices.

<svg width="600" height="600">
<path d="M200,200
a-50,-50 0 0,0 0,-30
a-50,-50 0 0,1 0,-30" fill="none" stroke="black"/>

<rect x="0" y="0" width="200" height="200"
style="stroke: none; fill: #FFCC33;">
<animateMotion
path="M200,200
a-50,-50 0 0,0 0,-30
a-50,-50 0 0,1 0,-30"
begin="0s" dur="3s" repeatCount="indefinite"
rotate="auto"
/>
</rect>
<rect x="-100" y="100" width="200" height="200"
style="stroke: none; fill: #FF0000;">
<animateMotion
path="M200,200
a-50,-50 0 0,0 0,-30
a-50,-50 0 0,1 0,-30"
begin="0s" dur="3s" repeatCount="indefinite"
rotate="auto"
/>
</rect>
<rect x="-200" y="200" width="200" height="200"
style="stroke: none; fill: #00FF00;">
<animateMotion
path="M200,200
a-50,-50 0 0,0 0,-30
a-50,-50 0 0,1 0,-30"
begin="0s" dur="3s" repeatCount="indefinite"
rotate="auto"
/>
</rect>

</svg>

AnimeJS Progressive Fill of an SVG path

Apparently there is no way to do it with pure CSS. ended up following this tutorial and it worked Great

https://medium.com/@anatacreative/handwriting-animation-with-svg-638931410cfa

Move an SVG object along a line or a path

As far as I know, there's no way to easily get the coordinates of an interpolated SVG path in D3, i.e. you might have to do the interpolation yourself.

To animate an SVG object along that path, you don't need to use D3 however. You can use the SVG <animateMotion> element to get a native SVG animation -- see here for an example.

How to do draw animation effect fill SVG?

Because your SVG file is not in the same shape as my logo. can you
please tell me how can I modify the path to achieve the exact same
shape. I don't have much knowledge about the illustrator by the way.

Unfortunately I do not use the illustrator. Path painted in Inkscape

Open the file from the previous answer to edit the path form inInkscape

<svg id="svg1" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" class="logo-white" width="184" height="95" viewBox="0 0 184 90.7" version="1.1">    <path class="draw-logo" fill="none" stroke="black" stroke-width="25" d="m81.3 30.4c0 0-11.7-9.8-17.5-13-3.8-2.2-9.9-4.6-15.3-5-5.7-0.4-11.7 0.4-16.8 2.9-4.8 2.3-8.7 6.3-11.8 10.7-3.2 4.5-5.6 9.8-6.3 15.2-0.9 6.2-0.4 12.9 2.3 18.6 2.7 5.7 7.5 10.6 12.9 13.8 5.2 3.1 11.6 4.8 17.7 4.5 5.8-0.2 11.6-2.7 16.6-5.7 21.6-13.1 34.2-37.9 55.1-52.2 5.8-4 12.1-8.3 19-9.1 5.7-0.6 11.9 0.9 16.8 3.9 6.7 4.1 12.3 10.6 15.2 17.9 2.8 6.9 3.4 15.1 1.4 22.2-1.8 6.3-6 12.2-11.3 16.1-6.3 4.6-14.5 7.8-22.2 7C127.1 77.2 118.6 70.3 111.3 63.7 104.7 57.8 95.9 42 95.9 42" />  </svg>

Animate SVG Line from Left to right Snap.svg

You're almost there, just missing two things.

First, you need to set the stroke-dasharray to '<length> <length>', this will create a "dashed" line with gaps/fill equal to the length of the entire line

lineDraw.attr({
fill:'none',
stroke:'#009FE3',
'stroke-dasharray': lineLength + ' ' + lineLength,
'stroke-dashoffset': lineLength,
'stroke-width' :6,
...

After this you need to animate the offset of the stroke to 0 using stoke-dashoffset

lineDraw.animate({
strokeDashoffset : 0
},3000, mina.easein)

working fiddle

How can I animate a progressive drawing of svg path?

There are three techniques listed in this answer:


There is an all-SVG solution that involves progressively modifying the stroke-dasharray for the shape to draw a longer and longer 'dash' followed by an enormous gap.

Demo: http://phrogz.net/svg/progressively-drawing-svg-path-via-dasharray.html

Relevant code:

var distancePerPoint = 1;
var drawFPS = 60;

var orig = document.querySelector('path'), length, timer;
orig.addEventListener('mouseover',startDrawingPath,false);
orig.addEventListener('mouseout', stopDrawingPath, false);

function startDrawingPath(){
length = 0;
orig.style.stroke = '#f60';
timer = setInterval(increaseLength,1000/drawFPS);
}

function increaseLength(){
var pathLength = orig.getTotalLength();
length += distancePerPoint;
orig.style.strokeDasharray = [length,pathLength].join(' ');
if (length >= pathLength) clearInterval(timer);
}

function stopDrawingPath(){
clearInterval(timer);
orig.style.stroke = '';
orig.style.strokeDasharray = '';
}

Alternatively, you can still use all SVG and choose to build the SVG path one command at a time:

Demo: http://phrogz.net/svg/progressively-cloning-svg-path.html

Relevant code:

// Assumes 'orig' and dup' are SVG paths
function addNextPathSegment(){
var nextIndex = dup.pathSegList.numberOfItems;
if (nextIndex<orig.pathSegList.numberOfItems){
var nextSegment = orig.pathSegList.getItem(nextIndex);
var segmentDup = cloneSVGPathSeg( dup, nextSegment );
dup.pathSegList.appendItem( segmentDup );
}
}

function cloneSVGPathSeg( path, seg ){
switch(seg.pathSegTypeAsLetter){
case 'M': return path.createSVGPathSegMovetoAbs(seg.x,seg.y); break;
case 'm': return path.createSVGPathSegMovetoRel(seg.x,seg.y); break;
case 'L': return path.createSVGPathSegLinetoAbs(seg.x,seg.y); break;
case 'l': return path.createSVGPathSegLinetoRel(seg.x,seg.y); break;
case 'H': return path.createSVGPathSegLinetoHorizontalAbs(seg.x); break;
case 'h': return path.createSVGPathSegLinetoHorizontalRel(seg.x); break;
case 'V': return path.createSVGPathSegLinetoVerticalAbs(seg.y); break;
case 'v': return path.createSVGPathSegLinetoVerticalRel(seg.y); break;
case 'C': return path.createSVGPathSegCurvetoCubicAbs(seg.x,seg.y,seg.x1,seg.y1,seg.x2,seg.y2); break;
case 'c': return path.createSVGPathSegCurvetoCubicRel(seg.x,seg.y,seg.x1,seg.y1,seg.x2,seg.y2); break;
case 'S': return path.createSVGPathSegCurvetoCubicSmoothAbs(seg.x,seg.y,seg.x2,seg.y2); break;
case 's': return path.createSVGPathSegCurvetoCubicSmoothRel(seg.x,seg.y,seg.x2,seg.y2); break;
case 'Q': return path.createSVGPathSegCurvetoQuadraticAbs(seg.x,seg.y,seg.x1,seg.y1); break;
case 'q': return path.createSVGPathSegCurvetoQuadraticRel(seg.x,seg.y,seg.x1,seg.y1); break;
case 'T': return path.createSVGPathSegCurvetoQuadraticSmoothAbs(seg.x,seg.y); break;
case 't': return path.createSVGPathSegCurvetoQuadraticSmoothRel(seg.x,seg.y); break;
case 'A': return path.createSVGPathSegArcAbs(seg.x,seg.y,seg.r1,seg.r2,seg.angle,seg.largeArcFlag,seg.sweepFlag); break;
case 'a': return path.createSVGPathSegArcRel(seg.x,seg.y,seg.r1,seg.r2,seg.angle,seg.largeArcFlag,seg.sweepFlag); break;
case 'z':
case 'Z': return path.createSVGPathSegClosePath(); break;
}
}

Finally, you may choose to draw your path to an HTML5 canvas by sampling the SVG path periodically and drawing to the canvas. (Note that the SVG path does not need to be displayed for this to happen; you can build an SVG path element entirely in JavaScript and sample it):

Demo: http://phrogz.net/svg/progressively-drawing-svg-path.html

Relevant code:

function startDrawingPath(){
points = [];
timer = setInterval(buildPath,1000/drawFPS);
}

// Assumes that 'orig' is an SVG path
function buildPath(){
var nextPoint = points.length * distancePerPoint;
var pathLength = orig.getTotalLength();
if (nextPoint <= pathLength){
points.push(orig.getPointAtLength(nextPoint));
redrawCanvas();
} else stopDrawingPath();
}

function redrawCanvas(){
clearCanvas();
ctx.beginPath();
ctx.moveTo(points[0].x,points[0].y);
for (var i=1;i<points.length;i++) ctx.lineTo(points[i].x,points[i].y);
ctx.stroke();
}


Related Topics



Leave a reply



Submit