Jump to content
GreenSock

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

Loops, arrays, and delays. oh - my

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

This is what I would like to happen:

1) Loop through a 2 dimensional array, each array contains a story segment: approx. 9 sentences/lines per segment.

2) Loop through the segment,  display 3 lines of the segment.  Each line is staggered for a fadeIn display

3) After the fade-in, Delay for short reading period before fading out the display.

 

Sounds easy enough, but I never got it right. I tried doing this using jQuery and setIntervals, then switched to setTimeouts, before

giving it a go with GSAP.  I'm lacking knowledge when it comes to looping with timers and the end result is I only see few sentences

from my multi-dimensional array.  Sorry, ES5 is all I know, but it feels like I'm missing a closure or something in this codepen

 

Here's what the html, and the javascript looks like:

HTML:

<body>
  <section class="hero"></section> 
  <section class="tribute">
    <div class="tribute-line1"></div>
    <div class="tribute-line2"></div>
    <div class="tribute-line3"></div>
  </section>
 </body>

Javascript:

$(function() {
  var tribStory = [
    [ 
      "Line 1-1", "Line 1-2", "",
      "Line 1-4", "Line 1-5", "",
      "Line 1-7", "Line 1-8", "Line 1-9"
    ],
    [ 
      "Line 2-1", "Line 2-2", "",
      "Line 2-4", "Line 2-5", "",
      "Line 2-7", "Line 2-8", "Line 2-9"
    ]
  ]; // end array
  
  var tl = new TimelineLite();
  var $line1 = $(".tribute-line1");
  var $line2 = $(".tribute-line2");
  var $line3 = $(".tribute-line3");
  var $currFade;
  var delay = 1000;
  var i = 0;    
  var storyLen = tribStory.length;
  
  function displayTribute( tribute, j ) { 
    console.log( tribute[j], tribute[j+1], tribute[j+2]);
    $line1.text( tribute[j] );
    $line2.text( tribute[j+1] );
    $line3.text( tribute[j+2] );
    tl.staggerTo( [$line1, $line2, $line3], 3, { opacity: 1 }, 0.5 )
      .delay(2).to( [$line1, $line2, $line3], 1, { opacity: 0 } );
  }
  
  var tribAnim = function() {

    if ( i < storyLen ) {
      
      var tribArray = tribStory[i]; 
      var tribArrLen = tribArray.length;
      
      for ( j = 0; j < tribArrLen; j+=3 ) {
        (function( tribArray, j){
          displayTribute( tribArray, j );
        }(tribArray,j));
      }
      i++;
    } 
    if ( i < storyLen ) tribAnim();
 
  };
  tribAnim();
 
}); 

 

See the Pen YeYVWp?editors=1010 by KerryRuddock (@KerryRuddock) on CodePen

Link to comment
Share on other sites

Thank you Craig.  Your pen is exactly what I am looking for.

 

I  wish I could understand why your javascript works and mine does not.

The thing is, with my code I do see the correct output at console.log... just not on the screen

which I'm sure is just my lack of knowledge.

 

I thought using a new TimeLineLite object on each iteration might do the trick,

but I'm convinced I tried this before my posting. This had had no impact on achieving a better result.

  function displayTribute( tribute, j ) { 
    var tl = new TimelineLite();
    console.log( tribute[j], tribute[j+1], tribute[j+2]);
    $line1.text( tribute[j] );
    $line2.text( tribute[j+1] );
    $line3.text( tribute[j+2] );
    tl.staggerTo( [$line1, $line2, $line3], 3, { opacity: 1 }, 0.5 )
       .to( [$line1, $line2, $line3], 1, { opacity: 0 }, "+2" );
  }

 

In your pen, could humor me,  when does onComplete: call animateStory? 

Is it at the end of tl.staggerTo()? or is it at the end of tl.to()?

 

function animateStory() {
  if (line < 9) {
    var tl = new TimelineMax({ onComplete: animateStory });
    line1.innerHTML = tribStory[j][line];
    line2.innerHTML = tribStory[j][line + 1];
    line3.innerHTML = tribStory[j][line + 2];
    tl.staggerTo([line1, line2, line3], 3, { opacity: 1 }, 0.5);
    tl.to([line1, line2, line3], 1, { opacity: 0 }, "+=1");
    line += 3;
  } else if (j < tribStory.length - 1) {
    j++;
    line = 0;
    animateStory();
  } else {
    console.log("all done");
  }
}
animateStory();

 

 

Link to comment
Share on other sites

That onComplete will fire at the end of the whole tl timeline when all three text elements have faded out completely.

 

You can add onComplete calls to the tweens too if you wanted/needed to do that. Adding one to a stagger is a bit of a different beast though. You have to remember that a stagger returns an array of tweens so adding an onComplete in the vars will fire each time one of the staggered elements finishes its animation.  To call a function after all the staggered elements have finished you would use onCompleteAll which goes in a different position. For a tween, it goes after the stagger number.

  • TweenMax.staggerTo( targets:Array, duration:Number, vars:Object, stagger:Number, onCompleteAll:Function, onCompleteAllParams:Array, onCompleteAllScope:* )

If the stagger is on a timeline, it goes after the position.

  • tl.staggerTo( targets:Array, duration:Number, vars:Object, stagger:Number, position:*, onCompleteAll:Function, onCompleteAllParams:Array, onCompleteScope:* ) 

Hopefully that helps. Happy tweening.

:)

 

  • Like 4
Link to comment
Share on other sites

The problem is simple. 

 

// Called repeatedly by for loop
function displayTribute( tribute, j ) { 
  
  // Executed immediately 
  console.log( tribute[j], tribute[j+1], tribute[j+2]);
  $line1.text( tribute[j] );
  $line2.text( tribute[j+1] );
  $line3.text( tribute[j+2] );
  
  // Happens some time in the future
  tl.staggerTo( [$line1, $line2, $line3], 3, { opacity: 1 }, 0.5 )
    .delay(2).to( [$line1, $line2, $line3], 1, { opacity: 0 } );
}

 

 

What's happening in the console is the same thing that's happening with your line elements. You need to change the text in the future, not now. You could do that with a callback using .call() or with the TextPlugin.

 

 

See the Pen GxbpBY by osublake (@osublake) on CodePen

 

  • Like 3
Link to comment
Share on other sites

Thanks Blake for those examples.  I played with the GSAP .call() and it worked fine and 

 

I stuck with Craig's example for my FCC project I was working on. Can be seen in this 

See the Pen oqrXXv by KerryRuddock (@KerryRuddock) on CodePen

 

I really liked the powerpoint presentation effect GSAP brought to this project.

  • Like 1
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.

×