Search code examples
javascriptanimationsvgsnap.svg

Animate dotted path, one dot after another


I'm using the latest version of Snap.svg to draw and animate a path within a SVG:

var s = Snap('#svg');
var getPath = s.path('M15 15L115 115');
var pathLength = getPath.getTotalLength();
getPath.attr({
  stroke: '#000',
  strokeWidth: 5,
  strokeDasharray: pathLength + ' ' + pathLength,
  strokeDashoffset: pathLength,
  strokeLinecap: 'round'
}).animate({
  strokeDashoffset: 0
}, 1500);

While this is working fine (as you can see here), I want to make it a dotted line, animated one dot after another.

I've built a quick prototype with circles (which you can see here), to illustrate the look and feel, but technically I want it to base on a custom path.

Basically I'm looking for a way to animate a dotted (complex) path; so a path with attributes would be as fine as circles on a path.


Solution

  • since stroke-dasharray can be an array of values you can leave the stroke-dashoffset at 0 and update the stroke-dasharray until you get to the complete line. something like this although this example is not really smooth and optimized.

    var s = Snap('#svg');
    var getPath = s.path('M15 15L115 115');
    var pathLength = getPath.getTotalLength();
    
    var perc = 0;
    var dotLength = 5;
    var gapLength = 4;
    
    getPath.attr({
        stroke: '#000',
        strokeWidth: 1,
        strokeDasharray: 0,
        strokeDashoffset: 0,
        strokeLinecap: 'round'
    });
    
    function updateLine(){
     perc +=1;
        if(perc>100){
            perc = 100;
        }
    var visibleLength = pathLength*perc/100;
    var drawnLength = 0;
        var cssValue = '';
        while(drawnLength < visibleLength){
         drawnLength += dotLength;
            if(drawnLength < visibleLength){
                cssValue += dotLength+ ' ';
                drawnLength += gapLength;
                if(drawnLength < visibleLength){
                    cssValue += gapLength+ ' ';
                }
            }else{
                cssValue += (visibleLength + dotLength - drawnLength)+ ' ';
            }
        }
        cssValue += pathLength;
        if(perc<100){
         setTimeout(updateLine, 100);
        }
        getPath.attr({
            strokeDasharray: cssValue
        });
    }
    
    updateLine();
    

    http://jsfiddle.net/EEe69/7/

    If you want the gaps to be "skipped" on the animation, you should substract them from the pathLength