Jump to content
GreenSock

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

Timeline for Multiple Buttons with pure JavaScript

Go to solution Solved by Diaco,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hi, I'm setting up a GSAP timeline for a share button. The site won't be using JQuery, so should be pure JS. But I'm struggling with getting the animation to work on only one button at a time. Clicking on one button fires the animation on all buttons. Pure JS is not my strong suit, so I need help with the JS logic and it's incorporation into the timelines. Thanks in advance!

 

Also, not sure if I'm doing something wrong or not, but closing the menu seems to have a slight delay on the recoil. Not sure why that is, but if anyone has any suggestions, I'd be grateful. Thx.

See the Pen 348f352c7690636348f5a48b88d92c05 by danrichman (@danrichman) on CodePen

Link to comment
Share on other sites

Hi level39 :)

 

pls try like this : 

 

var share = document.querySelectorAll(".share");

for(var i=share.length; i--{
  var tl = new TimelineLite();
  tl.to(share[i].querySelector('.share-select'),1,{autoAlpha:1,x:10});
  // add tweens to your timeline...
  tl.reversed(true);
  share[i].Anim=tl;
  share[i].querySelector('.share-button').addEventListener('click',function(){
    var Anim = this.parentNode.Anim ;
    Anim.reversed(!Anim.reversed());
  });
};
  • Like 3
Link to comment
Share on other sites

Hi,

 

I think you need to create separate TimelineMax (or Lite) instances for each of the animations as @Diaco aptly suggested. Below is another suggestion which, at the core of it, does create individual TimelineMax instances but some things are different:

JavaScript:

var shareSelect = document.querySelectorAll(".share-select");
var shareSelectButtons = document.querySelectorAll(".share-select .share-close");
var shareSelectDivider = document.querySelectorAll(".divider");
var timelines = [];
var timeline = null;
var shareButton = document.querySelectorAll('.share-button');
var shareClose = document.querySelectorAll('.share-close');
var length = shareButton.length;


for (var i = 0; i < length; i++) {
  timeline = new TimelineMax({ paused: true, reversed: true });
  timeline
    .fromTo(shareSelect[i], 0.25, { maxWidth: 0, x: -20 }, { maxWidth: 200, x: 0 }, 0)
    .staggerFromTo(shareSelectButtons[i], 0.5, { rotation: -10 }, { rotation: 0, ease: Back.easeOut }, 0)
    .fromTo(shareSelect[i], 0.5, { autoAlpha: 0 }, { autoAlpha: 1 }, 0)
    .fromTo(shareSelectButtons[i], 0.5, { x: -20 }, { x: 0 }, 0)
    .fromTo(shareSelectButtons[i], 1.1, { autoAlpha: 0 }, { autoAlpha: 1 }, 0)
    .fromTo(shareSelectDivider[i], 1.0, { autoAlpha: 0 }, { autoAlpha: 1 }, 0.25)
    .fromTo(shareSelectDivider[i], 0.5, { x: -50 }, { x: 0 }, 0)
    .timeScale(2.75);
  
  timelines[i] = timeline;
  
  (function(i) {
    shareButton[i].addEventListener('click', function() {
      timelines[i].reversed() ? timelines[i].play() : timelines[i].reverse();
    }, false);
    shareClose[i].addEventListener('click', function() {
      timelines[i].reverse();
    }, false);
  }(i));
}

What really is happening is:

  • The shareSelectButtons buttons are not simply targeting all the button elements inside .share-select elements but instead, it only targets .share-close button within.
  • There is an empty array called timelines first initialised.
  • The length is also pre-cached. 
  • Inside the loop:
    • A TimelineMax instance is first created.
    • All the animations that you originally defined are assigned to it but notice a difference that each of the shareSelectshareSelectButtons and shareSelectDivider elements are referenced individually by the use of the current iterator i.e. i variable since querySelectorAll returns all the matched elements (an array), you need to properly target the respective element in a given animation, otherwise all will animate. And because, our idea is to create individual timelines, we definitely need to target individual items for those individual tweens. Hope I am making sense here.
    • By the end of all tween additions into a timeline, the timeline itself is added into the main timelines array that we first created.
    • Then comes the closure function. I would suggest to read up here and then come back with questions if you have any.
    • Inside the closure, the code looks pretty much the same except that I have only gone with reversing the timeline when clicking on shareClose element instead of playing it forward or reversing it based on its reversed() state. Just makes sense to me. Your choice on this one though.
    • Another thing to note inside this closure is that only the respective timeline instance is played thanks to the i variable when either clicked on shareButton or shareClose button.
  • As for your question about the "delay" when reversing, it is because of the way your timeline is set up. Look at the shareSelectDivider's autoAlpha line for example that has an absolute position in the timeline that of 0.25 with a duration of 1 second. Similar thing is done for shareSelectButtons element's autoAlpha property with a duration of 1.1 seconds. All the other animations' durations are minimal in comparison. Eventually, when the animation reverses, a timeline would first start animating these longer durations and then, the more apparent shorter duration animations come into picture. Hard to explain without any visual cues. I suggest read up here. Just try to give all of them same duration of 0.5 and you will not notice any "delays".

Hope this helps.

  • Like 6
Link to comment
Share on other sites

  • Solution

ok , try this too :

 

var share = document.querySelectorAll(".share");

for(var i=share.length; i--{
  var share[i].Anim = new TimelineLite();
  tl.to(share[i].querySelector('.share-select'),1,{autoAlpha:1,x:10});
  // add tweens to your timeline here...
  tl.reversed(true);
  share[i].Anim=tl;
  shareBtnEv(i);
};

function shareBtnEv(i){
  var anim = share[i].Anim;
  share[i].querySelector('.share-button').addEventListener('click',function(){
    anim.reversed(!anim.reversed());
  });
  share[i].querySelector('.share-close').addEventListener('click',function(){
    anim.reverse();
  });
};
  • Like 3
Link to comment
Share on other sites

Thanks so much guys. I incorporated ideas from both solutions. 

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.
×