skip to Main Content

I am new to SVG animations, I looked in to SNAP SVG and other libraries, but I cannot find a way to achieve my goal.
I have a SVG file (or the SVG is directly integrated in HTML), that contains multiple paths.
I want to show the SVG image, one path at a time, and animate each path like the example at:

To better describe the result I want, please take a look at this image:
enter image description here

This is a svg element that contains 4 paths.
I want to show draw each path using javascript (not CSS), one after another, and animate them like:

enter image description here

From left to right, each point at a time. To obtain something like a hand drawn effect of the image.

Any suggestions is appreciated.

Thank you

2

Answers


  1. As mentioned in the comments, the linked SO Answer is a good starting point. If you want to stagger the drawing a crude, option would be to set the timeout on each path. (you would have to match the delay with the animations speed). I did this here wit the style attribute.

    Here a short Demo:

    .paths path {
         --line-length: 100;
         --delay: 0s;
         --animation-speed: 1s;
           
         stroke-dasharray: var(--line-length);
         stroke-dashoffset: var(--line-length);
         animation: drawPath var(--animation-speed) linear 1 forwards;  
         animation-delay: var(--delay);
    }
    
    @keyframes drawPath {
       0% { stroke-dashoffset: var(--line-length); }
       100% { stroke-dashoffset: 0; }
    }
    <svg width="200" height="200" fill="none" xmlns="http://www.w3.org/2000/svg">
      <g class="paths">
        <path d="M0 50 L 100 50"  stroke="red" stroke-width="5"/>
        <path d="M0 100 L 100 100" style="--delay: 1s" stroke="red" stroke-width="5"/>
        <path d="M0 150 L 100 150" style="--delay: 2s" stroke="red" stroke-width="5"/>
      </g>
    </svg>
    Login or Signup to reply.
  2. We can use the dash offset technique with Snap, which animates stroke-dashoffset. Example, including using prototypes with Snap is below, it will also allow chaining of animations.

    You can use an existing element rather than the string example below, using

    var element = Snap( someCSSSelector );

    You can run below example code below from tutorial site (my original code)

    var s = Snap("#svgout");
    
    var svgString1 = '<path id="s3" d="M 60 0 L 120 0 L 180 60 L 180 120 L 120 180 L 60 180 L 0 120 L 0 60 Z"  stroke="blue"/>';
    var svgString2 = '<path id="s3" d="M 60 0 L 120 0 L 180 60 L 180 120 L 120 180 L 60 180 L 0 120 L 0 60 Z"  stroke="red"/>';
    
    
    function Drawing( svgString, transformString, timeBetweenDraws ) {
        this.fragment = Snap.parse( svgString );
        this.pathArray = this.fragment.selectAll('path');
        this.group = s.g().transform( transformString ).drag();
        this.timeBetweenDraws = timeBetweenDraws;
    };
    
    Drawing.prototype.init = function( svgString, transformString ) {
          this.group.clear();
          this.currentPathIndex = 0;
    
    };
    
    Drawing.prototype.endReached = function() {
        if( this.currentPathIndex >= this.pathArray.length ) {
            return true;
        };
    };
    
    Drawing.prototype.callOnFinished = function() {
    }
    
    Drawing.prototype.initDraw = function() {
        this.init();
        this.draw();
    };
    
    Drawing.prototype.quickDraw = function() {
        this.init();
        this.timeBetweenDraws = 0;
        this.draw();
    };
    
    Drawing.prototype.draw = function() {         // this is the main animation bit
        if( this.endReached() ) {
            if( this.callOnFinished ) {
                this.callOnFinished();
                return
            };
        };
        var myPath = this.pathArray[ this.currentPathIndex ] ;
    
        this.leng = myPath.getTotalLength();
    
        this.group.append( myPath );
    
         myPath.attr({
           fill: 'none',
           "stroke-dasharray": this.leng + " " + this.leng,
           "stroke-dashoffset": this.leng
         });
    
         this.currentPathIndex++;
    
         myPath.animate({"stroke-dashoffset": 0}, this.timeBetweenDraws, mina.easeout, this.draw.bind( this ) );
    
    };
    
    
    
    var myDrawing1 = new Drawing( svgString1, 't0, 0, s1.8', 800 );
    var myDrawing2 = new Drawing( svgString2, 't69,50 s1.8', 3000 );
    var myDrawing3 = new Drawing( svgString2, 't150,150 s1.8', 5000 );
    
    myDrawing1.initDraw();
    myDrawing1.callOnFinished = function() { myDrawing2.initDraw() };
    myDrawing2.callOnFinished = function() { myDrawing3.initDraw() };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search