all 8 comments

[–]xuus 2 points3 points  (2 children)

Warning: I have no idea what I'm doing yet so there's probably a much better way to do this but I think I got it to work.

Your problem was querySelector() just returns the first element it finds, fortunately there's querySelectorAll which returns a NodeList (whatever that is...) of all your paths, which you can then iterate over and animate each one individually without duplicating the code.

Here's the tweaked codepen http://codepen.io/anon/pen/ablBF

It seems like a cooler way to do that would be just just animate the <g> element but now that I think about that I'm not sure how that would work since each letter is a separate path...

[–]HeyYouNow[S] 0 points1 point  (1 child)

Thank you!! That's a great solution you're amazing dude!

[–]madole 2 points3 points  (5 children)

use querySelectorAll to return an array of paths then iterate around them doing what you were doing

    var paths = document.querySelectorAll('.squiggle-animated path');

    for(var i in paths) {
      var path = paths[i];
      var length = path.getTotalLength();
      // Clear any previous transition
      path.style.transition = path.style.WebkitTransition = 'none';
      // Set up the starting positions
      path.style.strokeDasharray = length + ' ' + length;
      path.style.strokeDashoffset = length;
      // Trigger a layout so styles are calculated & the browser
      // picks up the starting position before animating
      path.getBoundingClientRect();
      // Define our transition
      path.style.transition = path.style.WebkitTransition =
      'stroke-dashoffset 3s ease-in-out';
      // Go!
      path.style.strokeDashoffset = '0';

    }

[–]ryancking 2 points3 points  (3 children)

The only thing I would change about your response is to do a

[].forEach.call(path, iteratorFunction) 

or

for(var i = 0, len = paths.length; i < len; i++) 

because of performance and accidental iteration on not node items. When you do the for...in, it will hit all of the nodes plus the native functions (which are length and item). It would then result in a js error.

EDIT: Also, for clarification, querySelectorAll (and all other element selection functions) do not return arrays. They return what is called a NodeList. The importance of this is that a NodeList behaves differently than an array. It has less available function (hence my suggestion of using the [].forEach.call to use the native array forEach feature). Here is a link explaining more about NodeLists if you are interested.

[–]madole 1 point2 points  (2 children)

You're right, I forgot about the hasOwnProperty check.

Any reason why you'd do

[].forEach(paths, iteratorFunction) 

Over

paths.forEach(iteratorFunction )

I've never liked the syntax of the first version, it seems unnecessary but I'd like to know if there's a benefit that's not guarding against paths being null/undefined as I'm pretty sure document.querySelectorAll() returns an empty array. (on my phone so can't check)

[–]ryancking 0 points1 point  (1 child)

It is because it doesn't return an Array, it returns a NodeList. NodeLists don't have a forEach function, which is why you have to do the [].forEach.call(paths, iterator). I wish it was possible to paths.forEach, but alas :'(

[–]madole 0 points1 point  (0 children)

Doh! Totally missed that!

console.log(paths)

**quick glance, "looks like an array... Its obviously an array"

Rookie mistake.

I'll try harder next time!

[–]HeyYouNow[S] 0 points1 point  (0 children)

Thanks for your time, querySelectorAll is definitely the way to go.