Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
gdgr

Stagger multiple tweens (TimelineLite) on array of elements

Recommended Posts

Hi everyone,
 
Only started using GSAP yesterday, until that point I was using Velocity.js on the basis of the rather disingenuous test that was originally listed on Julian's site (intentionally or not!)
 
So anyway I discovered that GSAP dunks all over it and I wanted in!
 
So, at the moment I'm making a UI pack for GSAP, since that was one of my most used features of Velocity, and it's great for front-end delights. It's going really well and I've taken to GSAP fairly quickly--but some things still elude me. One thing I'm trying to achieve is to do with one of the animations I've made, it's a 'shake', these are my first with multiple tween points, and I'm trying to figure out the way I'd go about successfully staggering a whole sequence on an array of elements. E.g.

case 'stagger.shake':
animate.to( 
element, 0.1, {left: "-=" + (nudge/2) + "px", ease:easing}
).to( 
element, 0.1, {left: "+=" + nudge + "px", ease:easing}
).to(
element, 0.1, {left: "-=" + nudge + "px", ease:easing}
).to( 
element, 0.1, {left: "+=" + nudge + "px", ease:easing}
).to(
element, 0.1, {left: "-=" + nudge + "px", ease:easing}
).to( 
element, 0.1, {left: "+=" + nudge + "px", ease:easing}
).to( 
element, 0.1, {left: "0px", ease:easing}
); break;

My initial approach was something like this: 

case 'stagger.shake':
animate.staggerTo( 
element, 0.1, {left: "-=" + (nudge/2) + "px", ease:easing}, stagger
).staggerTo( 
element, 0.1, {left: "+=" + nudge + "px", ease:easing}, stagger
).staggerTo(
element, 0.1, {left: "-=" + nudge + "px", ease:easing}, stagger
).staggerTo( 
element, 0.1, {left: "+=" + nudge + "px", ease:easing}, stagger
).staggerTo(
element, 0.1, {left: "-=" + nudge + "px", ease:easing}, stagger
).staggerTo( 
element, 0.1, {left: "+=" + nudge + "px", ease:easing}, stagger
).staggerTo( 
element, 0.1, {left: "0px", ease:easing}, stagger
); break;

I'm sure one of you guys knows exactly what I'm missing!

 

Seems like a great community here and looking forward to becoming a part of it. GSAP is awesome. And not in the desensitised meaning of the word, like genuinely awesome!

Link to comment
Share on other sites

Okay, I realised there was the option for that, and considered it, but I thought it rather pointless--I guess in hindsight it would allow someone to fork the pen and add the solution. I'll make one in a moment and post it :)

Link to comment
Share on other sites

if i understand correctly your target ; pls try this :

 

var animate = new TimelineMax();
var easing = defaultEasing = "Linear.easeNone";


function staggerShake(element) {
   for (i = 0; i < element.length; i++){
     animate.to(element[i], 0.1, {x: "-=10", ease:easing})
     .fromTo( element[i], 0.1, {x: "-=20"},{x: "+=20", ease:easing , repeat:3 , yoyo:true})
     .to( element[i], 0.15, {x: 0, ease:easing}) 
   }
}


$(document).ready(function() {
  staggerShake($('h1'));
});
////////////////////////////////////////////////////
/* var animate = new TimelineLite();
var easing = defaultEasing = "Linear.easeNone";


function staggerShake(elem) {
  elem.each(function(index,element){
    animate.to(element, 0.1, {x: "-=10", ease:easing})
    .fromTo( element, 0.1, {x: "-=20"},{x: "+=20", ease:easing , repeat:3 ,yoyo:true})
    .to( element, 0.1, {x: "0", ease:easing}); 
  }) 
}
staggerShake($('h1'));
*/

 

See the Pen OPyMgB by MAW (@MAW) on CodePen

  • Like 1
Link to comment
Share on other sites

This makes sense. It didn't occur to me that was how you'd enable the queue system.

 

Thank you!

Link to comment
Share on other sites

First of all, thanks for the kind words - it's really nice to hear compliments coming from an ex-Velocity user. And as far as that misleading performance demo on Julian's site, I have to take a good portion of the blame for that because there was a bug in the jQuery plugin for GSAP that would cause things to perform poorly in a very particular scenario which is exactly what Julian's demo was doing. That bug was fixed promptly, and Julian has since removed GSAP from his demo. He has been very nice about it. As far as I can tell, GSAP is at least as fast, and often faster than Velocity. Plus, as you have found, GSAP offers a lot more flexibility and power. But in fairness to Julian, he really wasn't trying to build a tool that's as robust as GSAP - Velocity is more for simple UI animations in the DOM. 

 

Anyway, I peeked at your demo and it looks like Diaco has already provided a solid solution (thanks Diaco!) but I wanted to offer my take on things in case it helps:

http://codepen.io/GreenSock/pen/1cc3cfbad8a99848a5aa9f8927332259/?editors=001

function staggerShake(elements, options) {
  options = options || {};
  //parse options and defaults
  var delay = options.delay || 0,
      ease = options.ease || options.easing || Linear.easeNone,
      stagger = (options.stagger == null) ? 0.3 : options.stagger || 0,
      repeat = options.repeat || 2,
      strength = options.strength || 1,
      duration = options.duration || 0.1,
      //now create the timeline that will house all the animations (we'll return this so you can easily control things or nest it in a master timeline or whatever)
      tl = new TimelineLite({delay:delay}),
      //based on the strength, determine the number of pixels we should move
      distance = strength * 20;
  tl.staggerTo(elements, duration, {x:"-=" + (distance / 2), ease:ease}, stagger)
    .staggerTo(elements, duration, {x:"+=" + distance, ease:ease, repeat:repeat * 2, yoyo:true}, stagger, duration) //notice we're inserting at a position of "duration" which just means we're starting this stagger sequence right after the first tween is done
    .staggerTo(elements, duration, {x:"+=" + (distance / 2), ease:ease}, stagger, duration * (repeat * 2 + 1)); //again, notice we're calculating the proper insertion point here. There are other ways we could do this, like looping through each element and creating a timeline instance for each, and nesting them in a master one in a staggered fashion, but I just liked the simplicity of using three staggerTo() calls and calculating the correct position.
  return tl;
}

$(document).ready(function() {
  staggerShake($('h1'), {stagger:0.2, strength:2, duration:0.1, repeat:2, ease:Power1.easeInOut});
});

The nice thing here is that everything is tucked into a nicely configurable staggerShake() function that returns a TimelineLite, thus you have total control of everything. You could tuck that resulting timeline into a master timeline, or tweak the timeScale or pause/resume/reverse or whatever the heck you want. Notice a few other conveniences: 

  1. I added a "strength" option so that you could make things shake more or less wildly. 1 is the default. 2 gives you twice as much movement, etc.
  2. I switched from animating "left" to "x" which is the same thing as transform: translateX() because it typically performs better, delivering GPU acceleration and sub-pixel rendering. Feel free to switch back if you prefer. 
  3. I added a "duration" option so you can make the animation longer or shorter.

Is this what you were looking for? 

  • Like 3
Link to comment
Share on other sites

  • 2 months later...

This was a remarkable answer Jack. You are brilliant.

 

My apologies for the delayed reply, you answered this the day before I started my new job and my workload has been immense.

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×