title: GSAP: Managing multiple tweens and timelines at once
body: <p>first things first, I am new to GSAP, so please bear with me. I try to give my best to describe what I am struggling with.</p>
  
  <p>In order to animate an SVG file I started diving into GSAP. I created several Tweens for different elements within my SVG file.
  Everything worked fine and ist animating as expected.</p>
  
  <p>Since I have a lot of elements to animate within my SVG, I started adding TimelineLite to have more control about the whole thing.</p>
  
  <p>At this point, my script file looked something like this:</p>
  
  <p>First I declared all the elements I'd like to animate:</p>
  
  <pre><code>this.phone = document.querySelector('#gsap-phone-svg');
  this.body = document.querySelectorAll('.gsap-phone-body');
  this.body.shadow = this.phone.querySelectorAll('.gsap-phone-body-shadow');
  this.body.mask = this.phone.querySelectorAll('.gsap-phone-body-mask');
  this.layer = this.phone.querySelectorAll('.gsap-phone-layer');
  this.screen = this.phone.querySelectorAll('.gsap-phone-screen');
  this.screen.clipPath = this.phone.querySelectorAll('.gsap-phone-screen-clipPath');
  .
  .
  .
  // many more following here
  </code></pre>
  
  <p>Than I created an Object to save my Tweens in:</p>
  
  <pre><code>const tweens = {};
  
  // creating tweens
  
  tweens.body = TweenMax.to(this.body, this.animDur/2,{
  y: this.maxExpand/6*-1,
  ease: this.ease
  });
  
  .
  .
  .
  
  // many more following here
  </code></pre>
  
  <p>At the end I added all my tweens to an temp array which I passed into a new TimelineLite() afterwards like so:</p>
  
  <pre><code>const tl = new TimelineLite();
  tl.add(tweensArray, 0, "start", 0.05);
  </code></pre>
  
  <p>Seems logic so far, I guess... Now here is the crux. You may have noticed or not that I have like more than 20 elements or so to animate. Thats why adding a tween for every element on its own becomes very confusing. Also I want the whole main timeline to be repetitive. The problem here is, that I want different easing for all my tweens on the "in-animation" than on the "out-animation", as well as I want to have no stagger on the "out-animation".</p>
  
  <p>All these little cruxes made me think about an alternative solution to manage the creation of my tweens and timelines.</p>
  
  <p>The most handy solution that came in my mind was to store all the information about my anim elements and timelines within an object:</p>
  
  <pre><code>const animation = {
     settings : {
        duration: 1.5,
        expansion: 1,
        easeIn: Elastic.easeOut.config(1, 0.5),
        easeOut: Power2.easeInOut
     },
     timelines : {
        main : {
           delay : 0,
           paused : true,
           align : 'start',
           stagger : 0.05,
        },
        test : {
           delay: 0,
           paused : true,
           align : 'start',
           stagger : 0.5
        }
     },
     items : {
        phone : {
           id : '#gsap-phone-svg',
           start : { },
           end : { },
           timeline : 'test',
        },
        body : {
           class : '.gsap-phone-body',
           start : {
              y : 0,
           },
           end : {
              y : -21,
           },
           timeline : 'test',
        },
        layer : {
           class : '.gsap-phone-layer',
           start : {
              y : 0,
           },
           end : {
              y : -62.5,
           },
           timeline : 'main',
        },
        radar : {
           class : '.gsap-phone-radar',
           start : {
              y : 0,
           },
           end : {
              y : -25,
           },
           timeline : 'main',
        },
        radarBase : {
           class : '.gsap-phone-radar-base',
           start: {
              y : 0,
           },
           end : {
              y: -16,
           },
           timeline : 'test',
        },
        ringOne : {
           class : '.gsap-phone-radar-ring-1',
           start : {
              y : 0,
           },
           end : {
              y: -25,
           },
           timeline : 'test',
        },
        ringTwo : {
           class : '.gsap-phone-radar-ring-2',
           start : {
              y : 0,
           },
           end : {
              y: -41,
           },
           timeline : 'main',
        },
        ringThree : {
           class : '.gsap-phone-radar-ring-3',
           start : {
              y : 0,
           },
           end : {
              y: -62.5,
           },
           timeline : 'main',
        },
        cancel : {
           class : '.gsap-phone-cancel',
           start : {
              y : 0,
           },
           end : {
              y: -50,
           },
           timeline : 'main',
        },
        submit : {
           class : '.gsap-phone-submit',
           start : {
              y : 0,
           },
           end : {
              y: -100,
           },
           timeline : 'main',
        }
     }
  };
  </code></pre>
  
  <p>Than I wrote this "createTweens" method to return the GSAP Tweens</p>
  
  <pre><code>/* create tweens */
  function createTweens(anim){
     const el = anim.items;
     const settings = anim.settings;
     const duration = settings.duration;
     const easeIn = settings.easeIn;
     const easeOut = settings.easeOut;
     const tweensIn = [];
     const tweensOut = [];
     let tempTween = null;
  
     for (const key in el){
        const curEl = el[key];
        const selector = curEl.class || el[key].id;
        const startPoint = curEl.start || '';
        const endPoint = curEl.end || '';
        const timeline = curEl.timeline || '';
        const nodes = document.querySelectorAll(selector);
  
        nodes.forEach(object =&gt; {
           tweensIn.push(getTween(object, endPoint, duration, easeIn, `${timeline}-in`));
           tweensOut.push(getTween(object, startPoint, duration, easeOut, `${timeline}-out`));
        });
     }
  
     function getTween(tw, twValues, twDur, twEase, tl){
        const vars = twValues;
        vars.paused = false;
        vars.ease = twEase;
        tempTween = TweenMax.to(tw, twDur/2, vars);
        tempTween.data = {
           timelineName : tl
        };
        return tempTween;
     }
  
     return tweensIn.concat(tweensOut);
  }
  </code></pre>
  
  <p>and another function to return the timelines:</p>
  
  <pre><code>/* create timelines */
  function createTimelines(anim, tweens){
     const el = anim.timelines;
     const timelines = {};
     // timelines.mainIn = new TimelineLite();
     // timelines.mainOut = new TimelineLite();
     const tweensForTimelines = {};
  
     for(const key in el){
        const delay = el[key].delay;
        const paused = el[key].paused;
        const align = el[key].align;
        const stagger = el[key].stagger;
        const vars = {};
        vars.paused = paused;
  
        timelines[`${key}-in`] = new TimelineLite(vars);
        timelines[`${key}-in`].delay = delay;
        timelines[`${key}-in`].align = align;
        timelines[`${key}-in`].stagger = stagger;
  
        timelines[`${key}-out`] = new TimelineLite(vars);
        timelines[`${key}-out`].delay = delay;
        timelines[`${key}-out`].align = align;
        timelines[`${key}-out`].stagger = stagger;
  
        tweensForTimelines[`${key}-in`] = [];
        tweensForTimelines[`${key}-out`] = [];
     }
  
     if(Object.keys(tweensForTimelines).length !== 0){
        for(let i = 0; i &lt; tweens.length; i++){
           const curTween = tweens[i];
           const tlTarget = curTween.data.timelineName;
           tweensForTimelines[tlTarget].push(curTween);
        }
     }
  
  
     for(const key in timelines){
        try{
           timelines[key].add(tweensForTimelines[key], timelines[key].delay, timelines[key].align, timelines[key].stagger);
           console.log(TweenMax.getTweensOf(timelines[key]));
           timelines[key].data = tweensForTimelines[key];
        } catch(e){
  
        }
     }
  
     return timelines;
  }
  </code></pre>
  
  <p>If I execute the following code than, it would play my "main-in" timeline.</p>
  
  <pre><code>const tweens = createTweens(animation);
  const timelines = createTimelines(animation, tweens);
  timelines['main-in'].play();
  </code></pre>
  
  <p>So far, this is actually working. But if I try to add the "main-in" timeline to a new timeline, its not working anymore.</p>
  
  <pre><code>const anotherTimeline = new TimelineLite();
  anotherTimeline.add(timelines['main-in']);
  anotherTimeline.play();
  </code></pre>
  
  <p>In order to debug this, I tried </p>
  
  <pre><code>TweenMax.getTweensOf(anotherTimeline);
  </code></pre>
  
  <p>but all this returns is an empty Array. Then I logged the same for my "main-in" timeline:</p>
  
  <pre><code>console.log(TweenMax.getTweensOf(timelines['main-in'])); 
  </code></pre>
  
  <p>also returning an empty Array which is very confusing to me, since even though this timeline seems to be empty, it plays my "in-animation" on:</p>
  
  <pre><code>timelines['main-in'].play()
  </code></pre>
  
  <p>I am really stuck here and would really appreciate some help from the more advanced users or simply anyone who has an idea for this. I hope you guys were able to follow me ... in case not, have a look at the codepen provided..</p>
  
  <p>UPDATE: <a href="http://codepen.io/anon/pen/vyEvbJ" rel="nofollow noreferrer">Click for Codepen DEMO</a></p>
  
  <p>Thanks in advance!</p>