Comm 328 Responsive Web Design

Finding SVG Path Lengths and Animating On Reveal

We can enhance our SVG line animations by adding a bit of JavaScript. Instead of using the Web Inspector to guess the length of our paths by trial and error, we can actually use JavaScript to find the length. Additionally, we can add JavaScript to trigger the animations as an illustration scrolls into view instead of having them all trigger when the page loads.

Automatically Calculating the Path Length

The following script can help you animate multiple svg illustrations on a page by automatically calculating the length of a path. This is done using the JavaScript method getTotalLength().

The JavaScript snippet below creates a function that will look for all of the paths we've marked to animate. It will then calculate the length of the path and set the set the stroke-dasharray and stroke-dashoffset properties to the path length.

We mark a path we want to animate by adding a class of animate to the path element.

<path class="animate" d="M201.433047,86.0936534 C197.093441,64.3956216 202.338807,80.6307488 180.881761,54.1249853 C173.697965,45.2508842 167.384379,35.7009663 160.330474,26.7232698 C159.000377,25.0304192 157.689118,23.1191154 155.763522,22.1563173 C139.885694,14.2174033 141.961377,62.043444 142.062664,63.2588905 C143.546274,81.0622113 162.774689,99.9552499 171.747856,108.928416" id="path-1" stroke="#979797">

The JavaScript code is listed below.

var initAnimations = function() {
  // find all of the paths marked with the animate class
  var $animatable = $('path.animate');

  // loop through each path and set the 
  // stroke-dasharray and stroke-dashoffset to path length
  $animatable.each( function() {
    var pathLength = this.getTotalLength();

    this.setAttribute('stroke-dasharray', pathLength+' '+pathLength);
    this.setAttribute('stroke-dashoffset', pathLength);
  });
}

  initAnimations();  // execute the function

Because of how the SVG line animation works, attaching this function to your page will actually have the effect of hiding the paths you want to animate. In order to make the animation happen, you have to add the trigger and animated state in your CSS.

The CSS below will create an animation on the hover state of the SVG (with an id of 'sloppy-bear' in this example). When the SVG is hovered over, the stroke-dashoffset property will be set to 0. The transition property is also set so that change of the property from the value of the path length (set by the JavaScript) to 0 is animated.

#sloppy-bear:hover .animate {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1s ease-in;
}

See the demonstration of this JavaScript function below. View the source for more info.

Trigger Animations on Reveal

If we wanted to make our animations a bit more sophisticated, we could add more JavaScript to actually trigger the animations when the SVG is scrolled into view rather than on the hover state.

To achieve the effect, we need JavaScript to figure out if the animation is in view. We do this by finding the height of the window and adding it to the number of pixels we've scrolled down the page. We compare this number to the number of pixels from the top of the page the animation is. If the result of the window height and scrolled amount is greater than the number of pixels the animation is offset, then we know it is in view.

In the script below, we find all elements with the class revealOnScroll and the check to see if they are in the page window. If they are, we add the class animated. We can use the animated class to create the animation state and transition in CSS.

$(document).ready(function() {
// set the revealOnScroll function to run when we scroll the page
var $window = $(window);
$window.on('scroll', revealOnScroll);

function revealOnScroll() {
  var scrolled = $window.scrollTop(),
  win_height_padded = $window.height() * 1.1;

  // Animation is showing...
  $("path.revealOnScroll:not(.animated)").each(function () {
    var $this = $(this);
    var offsetTop = $this.offset().top;

    // Add the animated class to trigger the animation
    if (scrolled + win_height_padded > offsetTop) {
      $this.addClass('animated');
    }
  });
}

revealOnScroll(); // Call the reavealOnScroll when the page is ready
});

The jQuery selector $("path.revealOnScroll:not(.animated)") is designed to ensure that the JavaScript ignores items that have been previously animated. Each time something is animated, it has the animated class added. This means each SVG will only trigger once. You'll have to reload the page to see the animation again.

Combining Auto Path Lengths and Reveal on Scroll Trigger

You can combine the previous two functions with some slight modification to enable multiple animations on each page that will trigger when they are scrolled into view.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script>
  var initAnimations = function() {
	  var $animatable = $('.revealOnScroll');

	  $animatable.each( function() {
      var pathLength = this.getTotalLength();

      this.setAttribute('stroke-dasharray', pathLength+' '+pathLength);
      this.setAttribute('stroke-dashoffset', pathLength);
    });
  }


  $(document).ready(function() {
    var $window = $(window);
    $window.on('scroll', revealOnScroll);

    function revealOnScroll() {
      var scrolled = $window.scrollTop(),
      win_height_padded = $window.height() * 1.1;

      // Is animation showing?
      $(".revealOnScroll:not(.animated)").each(function () {
        // animation scrolled into view
        var $this = $(this);
        var offsetTop = $this.offset().top;

        // Add the animated class to trigger the animation
        if (scrolled + win_height_padded > offsetTop) {
          $this.addClass('animated');
        }
      });
    }

    initAnimations(); // Start the initiation for the animations
    revealOnScroll(); // Call the revealOnScroll when the page is ready
  });
</script>

Any path element with a class of revealOnScroll will have the animated class added as soon as it's scrolled into view.

Adjusting Animation Timing

You can adjust the animation timing by modifying the transition property. You can adjust the timing by modifying the transition-duration.

#sloppy-bear .animated {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 
.5s ease-in; }

You can also adjust the animation delay by adding a transition-delay value.

#sloppy-bear .animated {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset .5s ease-in 
1s; }

Modifying individual animations

You can also leverage classes and ids in your CSS selectors to create different timings and delays for different parts of an animation or completely different animations.

In the example below we use the timings to stagger each path animation. View the source code for explanation.

More Resources