Search code examples
htmlcsssvgcss-animationsline-drawing

How to control the timing of CSS3 animation


I'm working on the SVG line drawing animation as shown below.

enter image description here

So what am I doing is animate the ear by using stroke-dasharray and continue with the dots.

I managed to finish the ear drawing, but I don't know how to control the dots' timing. Following are my animation steps:

  1. Ear drawing animation within 5s
  2. After 5s, continue with the dots animation (animate row by row)
  3. When finish the dots animation, loop back to the 1st step

This is my code, but it blinking gradually. How do I adjust the timing?

.firstpath {
  stroke-dasharray: 1500;
  animation: firstanimate 5s linear forwards infinite;
}
@keyframes firstanimate {
  from {
    stroke-dashoffset: 1500;
  }
  to {
    stroke-dashoffset: 0;
  }
}
.secondpath {
  stroke-dasharray: 500;
  animation: secondanimate 5s linear forwards infinite;
}
@keyframes secondanimate {
  from {
    stroke-dashoffset: 500;
  }
  to {
    stroke-dashoffset: 0;
  }
}
.thirdpath {
  stroke-dasharray: 500;
  animation: thirdanimate 5s linear forwards infinite;
}
@keyframes thirdanimate {
  from {
    stroke-dashoffset: 500;
  }
  to {
    stroke-dashoffset: 0;
  }
}
.row1col1 {
  animation-delay: 1s;
  animation: blink 2s step-start 0s infinite;
  -webkit-animation: blink 2s step-start 0s infinite;
}
@keyframes blink {
  0% {
    opacity: 1.0;
  }
  50% {
    opacity: 0.0;
  }
  100% {
    opacity: 1.0;
  }
}
@-webkit-keyframes blink {
  0% {
    opacity: 1.0;
  }
  50% {
    opacity: 0.0;
  }
  100% {
    opacity: 1.0;
  }
}
<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" width="841.89px" height="595.28px" viewBox="0 0 841.89 595.28" enable-background="new 0 0 841.89 595.28" xml:space="preserve">

  <g>
    <path class="firstpath" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
			M253.441,284.167c0,0-0.883-14.535,15.429-18.551c5.364-1.32,15.943-0.665,21.667,6.79c13.859,18.051-3.235,32.286-8.087,37.262
			c-4.853,4.979-7.713,21.027-17.543,20.528c-9.829-0.497-12.69-6.717-12.317-11.818" />

    <path class="secondpath" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
			M285.249,285.252c0,0,0.654-8.212-8.864-10.544c-9.519-2.334-16.796,8.211-10.825,17.449c2.613-1.12,5.226,0.652,5.599,2.52
			c0.373,1.866-1.213,4.199-3.826,4.199" />

    <path class="thirdpath" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
			M257.815,307.553c0,0-3.732,5.879,2.333,8.118c6.065,2.241,5.318-8.118,8.865-9.237c3.545-1.119,11.943-2.519,11.943-10.265
			c0-7.744-6.398-16.451-17.522-11.958" />
  </g>

  <line class="row1col1" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="319.41" y1="287.987" x2="324.156" y2="286.627" />

  <line fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="328.667" y1="285.335" x2="332.744" y2="284.167" />

  <line fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="338.25" y1="301.171" x2="343.41" y2="301.171" />

  <line fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="328.667" y1="301.171" x2="333.75" y2="301.171" />

  <line fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="319.41" y1="301.171" x2="324.156" y2="301.171" />

  <line fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="313.741" y1="314.625" x2="319.41" y2="315.987" />

  <line fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="323.741" y1="316.746" x2="329.667" y2="318.142" />

</svg>


Solution

  • The way the parts of the shape are formed, this would require multiple keyframe animations to work the way you intend for it to.

    The following are what you have to do:

    • The ear animation though it is expected to complete at 5s mark should not start its next iteration till the animation of the lines are completed. That is, the ear should stay idle during the amount of time taken by the lines to complete their animation. Hence, we have to set animation-duration for the ear such that it covers the amount of time required for the lines to complete their animation. Here, each line component takes 1s and so total animation-duration for all elements (ear and lines) would be 12s.
    • The ear animation should be complete at 5s mark (out of a total duration of 12s) and hence the from - to keyframe setting should be replaced with percentages. Ear animation should start at 0% and attain its completion at 41% (which is roughly the 5s mark). From there, it should hold its position till 100% (12s) mark (that is basically till the lines complete their animation).
    • Each line component should start after their previous part has completed its animation and so the row1col1 should start at 41% which is when the ear becomes fully visible (till that point it should remain invisible).
    • The row1col1 needs 1s to animation (which is roughly 8% of 12s) and hence the row1col2 should wait till 49% of the total duration to start its animation. Similarly row2col1 should start at 57%, row2col2 should start at 66% and so on.
    • If the lines need to slowly fade in, then make it start with opacity: 0 at 41% and get opacity: 1 at 49% (for row1col1 and so on for the rest). On the other hand if you need them to appear instantaneously, reduce the percentage where it gets opacity: 1. In the snippet, I have made the row1col1 reach opacity: 1 at 42% itself (which is like 0.12s).

    Notes:

    • I have also modified the stroke-dasharray settings of the ear's components to avoid the delay that was originally there between completion of ear's animation and start of the line's animation.
    • I would also recommend you to get some SVG expert's help to check if the no. of parts can be minimized as it would reduce no. of keyframes required etc. Unfortunately, my SVG knowledge is limited and so I can't help much with it.

    .firstpath {
      stroke-dasharray: 150;
      animation: firstanimate 12s linear forwards infinite;
    }
    @keyframes firstanimate {
      0% {
        stroke-dashoffset: 150;
      }
      41% {
        stroke-dashoffset: 0;
      }
    }
    .secondpath {
      stroke-dasharray: 100;
      animation: secondanimate 12s linear forwards infinite;
    }
    @keyframes secondanimate {
      0% {
        stroke-dashoffset: 100;
      }
      41% {
        stroke-dashoffset: 0;
      }
    }
    .thirdpath {
      stroke-dasharray: 65;
      animation: thirdanimate 12s linear forwards infinite;
    }
    @keyframes thirdanimate {
      0% {
        stroke-dashoffset: 65;
      }
      41% {
        stroke-dashoffset: 0;
      }
    }
    line {
      opacity: 0;
    }
    .row1col1 {
      animation: blink 12s linear forwards infinite;
    }
    @keyframes blink {
      41% {
        opacity: 0;
      }
      42%, 100% {
        opacity: 1;
      }  
    
    }
    .row1col2 {
      animation: blink2 12s linear forwards infinite;
    }
    @keyframes blink2 {
      49% {
        opacity: 0;
      }
      50%, 100% {
        opacity: 1;
      }
    }
    .row2col1 {
      animation: blink3 12s linear forwards infinite;
    }
    @keyframes blink3 {
      57% {
        opacity: 0;
      }
      58%, 100% {
        opacity: 1;
      }
    }
    .row2col2 {
      animation: blink4 12s linear forwards infinite;
    }
    @keyframes blink4 {
      66% {
        opacity: 0;
      }
      67%, 100% {
        opacity: 1;
      }
    }
    .row2col3 {
      animation: blink5 12s linear forwards infinite;
    }
    @keyframes blink5 {
      75% {
        opacity: 0;
      }
      76%, 100% {
        opacity: 1;
      }
    }
    .row3col1 {
      animation: blink6 12s linear forwards infinite;
    }
    @keyframes blink6 {
      84% {
        opacity: 0;
      }
      85%, 100% {
        opacity: 1;
      }
    }
    
    .row3col2 {
      animation: blink7 12s linear forwards infinite;
    }
    @keyframes blink7 {
      92% {
        opacity: 0;
      }
      93%, 100% {
        opacity: 1;
      }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
    <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" width="841.89px" height="595.28px" viewBox="0 0 841.89 595.28" enable-background="new 0 0 841.89 595.28" xml:space="preserve">
    
      <g>
        <path class="firstpath" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
    			M253.441,284.167c0,0-0.883-14.535,15.429-18.551c5.364-1.32,15.943-0.665,21.667,6.79c13.859,18.051-3.235,32.286-8.087,37.262
    			c-4.853,4.979-7.713,21.027-17.543,20.528c-9.829-0.497-12.69-6.717-12.317-11.818" />
    
        <path class="secondpath" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
    			M285.249,285.252c0,0,0.654-8.212-8.864-10.544c-9.519-2.334-16.796,8.211-10.825,17.449c2.613-1.12,5.226,0.652,5.599,2.52
    			c0.373,1.866-1.213,4.199-3.826,4.199" />
    
        <path class="thirdpath" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
    			M257.815,307.553c0,0-3.732,5.879,2.333,8.118c6.065,2.241,5.318-8.118,8.865-9.237c3.545-1.119,11.943-2.519,11.943-10.265
    			c0-7.744-6.398-16.451-17.522-11.958" />
      </g>
    
      <line class="row1col1" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="319.41" y1="287.987" x2="324.156" y2="286.627" />
    
      <line class="row1col2" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="328.667" y1="285.335" x2="332.744" y2="284.167" />
    
      <line class="row2col3" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="338.25" y1="301.171" x2="343.41" y2="301.171" />
    
      <line class="row2col2" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="328.667" y1="301.171" x2="333.75" y2="301.171" />
    
      <line class="row2col1" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="319.41" y1="301.171" x2="324.156" y2="301.171" />
    
      <line class="row3col1" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="313.741" y1="314.625" x2="319.41" y2="315.987" />
    
      <line class="row3col2" fill="none" stroke="#000000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="323.741" y1="316.746" x2="329.667" y2="318.142" />
    
    </svg>