Jump to content
GreenSock

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

looping through timeline and fill array with push

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 studying the video-tutorial "advanced sequencing - meet the blobs".
http://hub.tutsplus.com/tutorials/timelinelite-ultimate-starter-guide-advanced-sequencing--active-10331
by Carl Schooff
I want to rebuild it in javascript not AS.
in the video at 25'45 I'm stucked with looping through the blobani timeline with insertMultiple and push the created timelines into an array.
 

 var blobTweens = new Array();

function createBlobs() {

for (var i=0; i<10; i++){  
var blob = $("#blob");

var blobani = new TimelineLite();
blobani.insertMultiple([
    TweenLite.to(blob, 2, {x:480}),
    TweenLite.to(blob, 0.5, {y:-250}),
    TweenLite.to(blob, 0.5, {rotation:360, delay:.1}),
    TweenLite.to(blob, 0.5, {y:-140, delay:0.5})
    ]);
blobTweens.push(blobani);
or
blobTweens = (blobani);
}
}

I can't push the timelines that were created by the for loop into the blobTweens array. can you please help me with the right javascript syntax for this wonderful idea to create multiple objects?

thank you for the timeline guide videos and for your answer

Michael
 

Link to comment
Share on other sites

Hi Michael and welcome to the forums.

 

You're very close in fact to add an object to an array the most common way is using push, the first code you have.

 

Also you can create arrays via constructor, like you did, or literal. In this matter there's a lot of discussion but it has been said quite a lot that literal arrays are better and faster in terms of passing the data to it. So you could do it like this:

var blobTweens = [];//array literal 

function createBlobs() {

for (var i=0; i<10; i++){  
var blob = $("#blob");

var blobani = new TimelineLite();
blobani.insertMultiple([
    TweenLite.to(blob, 2, {x:480}),
    TweenLite.to(blob, 0.5, {y:-250}),
    TweenLite.to(blob, 0.5, {rotation:360, delay:.1}),
    TweenLite.to(blob, 0.5, {y:-140, delay:0.5})
    ]);
blobTweens.push(blobani);
}
}

Read this article and in general this blog, is quite useful:

http://www.2ality.com/2013/07/meta-style-guide.html

 

Also read this for some differences between array constructor and literals:

http://www.mattlunn.me.uk/blog/2012/04/the-use-of-literals-vs-constructors/

 

Hope this helps,

Rodrigo.

Link to comment
Share on other sites

Hi Mike, just to add one thing... I noticed that in your loop you're adding new elements with the same id:

for (var i=0; i<10; i++){ 
var blob = $("#blob"); // should be $("<div class='blob' />");

I would suggest you to use classes instead of ids. Having multiple elements with the same id on the page may break your script. Validators will complain, browsers will get you away with it, but selectors like getElementById() will break, which will result to non-working JS code. 

 

Ico 

  • Like 1
Link to comment
Share on other sites

Hi rhernando, hi bassta

thanks for answering.
I learned about literal arrays and the links to javascript sites were extremely helpful.

And:

I tried the proposal with $("<div class='blob' />"), but I couldn't get it to work.

here my codepen:

See the Pen vnhuF by codepenmicha (@codepenmicha) on CodePen

It seems this it not what you mean.

 

sorry about making it big, but I'm faszinated of the idea of multiple objects and I like to show you the actionscript from Carl first (just for orientation) and then my attempt to get it work with javascript and tweenMax only.

here is the actionscript (from: http://hub.tutsplus.com/tutorials/timelinelite-ultimate-starter-guide-advanced-sequencing--active-10331):

package {

import flash.display.MovieClip;
import com.greensock.*;
import com.greensock.easing.*;
//import com.greensock.TweenAlign;
import flash.events.Event;
import flash.events.MouseEvent;
import fl.controls.Button;
import fl.controls.Slider;
import fl.events.SliderEvent;



public class MultipleNestedTimelines extends MovieClip {

    public var tl:TimelineMax;
    public var blobTweens:Array;

    //stage instances


    public var slider:Slider;
    public var restart_btn:Button;

    public var meet_mc:MovieClip;
    public var the_mc:MovieClip;
    public var blobs_mc:MovieClip;

    public function MultipleNestedTimelines():void {

        if (stage) {
            init();
        }
        else {
            addEventListener(Event.ADDED_TO_STAGE, init);
        }
    }

    private function init(e:Event = null):void {

        //set up nav events
        slider.addEventListener(SliderEvent.THUMB_DRAG, sliderChange);
        restart_btn.addEventListener(MouseEvent.CLICK, restart);

        blobTweens = [];


        //create blobs and their respective timeline animations

        createBlobs();

        createMasterTimeline();

    }


    private function createBlobs():void {

        for (var i:int = 0; i < 30; i++) {
            var blob:Blob = new Blob();
            blob.y = 475;
            addChild(blob);

            var blobAni:TimelineLite = new TimelineLite();

            blobAni.insertMultiple([
               TweenLite.to( blob, 2, {x:680, ease:Linear.easeNone}),
               TweenLite.to( blob, .5, {y:Math.random() * 200}),
               TweenLite.to( blob, .9, {rotation:360, delay:.1}),
                TweenMax.to( blob, .5, {y:230, ease:Quad.easeIn, delay:.5})
               ]);
            
            blobTweens.push(blobAni);

        }
    }



    private function createMasterTimeline():void {


        tl = new TimelineMax({onUpdate:trackProgress});
        
        //pass an array of clips to allFrom();
        tl.insertMultiple( TweenMax.allFrom( [meet_mc, the_mc, blobs_mc], .5, {scaleX:0, scaleY:0, ease:Back.easeOut} ), 0, TweenAlign.NORMAL, .3);
        
        
        //blobTweens array was populated with TimelineLite's in createBlobs()
        tl.appendMultiple(blobTweens, 0, TweenAlign.NORMAL, .4);

    }

    //slider and nav controls
    private function trackProgress():void {
        slider.value = tl.currentProgress * 100;
    }

    private function sliderChange(e:SliderEvent):void {
        tl.pause();
        tl.currentProgress = slider.value * .01;
    }

    private function restart(e:MouseEvent):void {
        tl.restart();
    }
}
}

and here is my attempt in codepen:

See the Pen oAgcD by codepenmicha (@codepenmicha) on CodePen

$(window).load(function(){
	
var tl = new TimelineMax;// ({onUpdate:myupdateHandler});
	var blobTweens = [];//array literal 
	
	
	createBlobs();
	createMasterTimeline();		








function createBlobs() {

	for (var i=0; i<4; i++){  

		var blob = $("#blob"); 
		//var blob = $("<div class='blob' />");// doesn't work
		//var blob = $(".blob");
	
		var blobAni = new TimelineLite();
		
    blobAni.insertMultiple([
	TweenLite.to(blob, 2, {x:480}),
	TweenLite.to(blob, 0.5, {y:-250}),
	TweenLite.to(blob, 0.5, {rotation:350, delay:.1}),
	TweenLite.to(blob, 0.5, {y:-140, delay:0.5})
    ]);
		
	blobTweens.push(blobAni);
   }
}



function createMasterTimeline() {
   tl = new TimelineMax();
   tl.appendMultiple(blobTweens, 0, "normal", .5);
   //tl.add(blobTweens, 0, "normal", .5);
			
}

});

How do I check if blobTweens.push(blobAni); works?

and how do I fill the MasterTimeline with the looped timeline so that I get multiple instances of blob?
 

 

I hope this is interesting

thank you for advices

Michael

Link to comment
Share on other sites

Hi Michael,

 

What Chrysto meant by using the class selector is that in html you can create a series of objects that can share the same class name, for example the buttons in a menu, you give them the same class and they all share their CSS styles. This gives you the possibility to select all of them via JQuery, like this:

var blobs = $("div.blob");

So all the elements with a "blob" class will be in that particular JQuery object. Then all you have to do is iterate through all the elements in that particular collection and create the individual timeline, add that timeline to the array and finally include that array in your master timeline.

 

I forked your codepen and made those modifications, you can see it here:

See the Pen nbprE by rhernando (@rhernando) on CodePen

 

Also I'd recommend you to read a little more about javascript and JQuery. For the basics of javascript read the following links:

A good guide to start with JQuery is the site's learning center:

http://learn.jquery.com/

 

And finally take a look at the add method in the API docs is far better than insert multiple for this cases.

 

Hope this helps,

Rodrigo.

  • Like 1
Link to comment
Share on other sites

Hi,

 

Also as a suggestion you could use the bezier plugin to describe the complete path of the blobs.

oxwm.jpg

 

In the image the blue line would be the path you'll have to describe with bezier.

 

Cheers,

Rodrigo.

Link to comment
Share on other sites

Great work, guys.

Excellent codepen, Rodrigo.

 

Michael,

 

The activetuts tutorial is definitely a bit out-dated as the most recent version of GSAP, version 12 makes it much easier to add tweens to timelines. As Rodrigo, noted insertMultiple and appendMultiple have been deprecated in favor of add.

 

Still, converting the tutorial to JS is a noble challenge and certainly a good way to learn some of the nuances of javascript and the GSAP API. 

 

Rodrigo's codepen is definitely a great example to study. 

Link to comment
Share on other sites

thank you very much for staying with me.
I've learned to declare an array literally.  And to use and go for class with $(".blob") instead of #blob.
And to use a chain of blobani.to().to().to(); instaed of insertMultiply.

To further understand Rodrigos genial codepen, I reduced some things: I delete the timelineDelay and therefor use a staggernumber after "sequnce".
so this is my codepen (with $.each loop):

See the Pen fhaIq by codepenmicha (@codepenmicha) on CodePen

$(window).load(function(){
	
	var tl = new TimelineMax();
	var	blobTweens = [];
	var restartBtn = $("button#restartBtn");
  
function createBlobs() {
	var blob = $(".blob");


	$.each(blob, 
	//for(i=0; i < 7; i++){
	
	function(index, element) {
						  
		var blobAni = new TimelineLite({});

		blobAni
			.to(element, 2, {x:480})
			.to(element, 0.5, {y:-250}, '-=1.75')
			.to(element, 0.5, {rotation:350}, '-=1.75')
			.to(element, 0.5, {y:-140});

		blobTweens.push(blobAni);
	}
)}

	function createMasterTimeline() {
		tl.add(blobTweens, 0, "sequence", -2.0); 		
	}
  
createBlobs();
createMasterTimeline();	
	  
});

My question is: can you help me to express the loop with a javascript for(i=0; i < array.length; i++) loop instead with the jquery each loop?
codepen link:

See the Pen satGp by codepenmicha (@codepenmicha) on CodePen

just for my understanding.
Second question is: I thought the advantage of Calrs method in the activetuts tutorial was: to have only one html element and multiply it through the javascript code. Am I wrong with this idea?

thanx for working with you.
Michael

 

Link to comment
Share on other sites

Hi Michael,

 

In terms of using a for loop instead of jquery's each loop, the thing is that jquery is already loaded and being used in the app so, why not just stick with and take full advantage of it?. As you'll see is far less code than vanilla js. Not that I'm against vanilla js, I found, quoting Carl, quite a noble challenge porting jquery code to vanilla js, but you'll face quite some challenges along that path. Just my two cents.

 

Well in terms of working with a for loop you first need to tell the loop where and what is looking for. Since you created a jquery collection (an object that pretty much works and behaves like an array - thanks for pointing that out Jack ;) ), all the blobs elements are there, so first you need to find how many there are:

//jquery collection with all the blobs
var blob = $(".blob");
var blobAmount = blob.length;//how many blobs there are

Now you have the number of elements and where they are you can tell the loop how many times it has to iterate and where it has to look:

for(var i = 0; i < blobAmount; i++)
{
    var blobAni = new TimelineLite();

    //here you tell the loop to look in the blob collection for the element with that
    //index which is given by the current value of i
    var element = blob[i];

    blobAni
        .to(element, 2, {x:480})
	.to(element, 0.5, {y:-250}, '-=1.75')
	.to(element, 0.5, {rotation:350}, '-=1.75')
	.to(element, 0.5, {y:-140});

    //finally we add the timeline to the timelines array
    blobTweens.push(blobAni);
}

And the rest of the code is the same.

 

As for the second question, well I'm not a great As connoisseur, but is a little more easier doing that in AS than in JS. In the latter you have to create a string and add that to a container, while in AS you just create a MC add it to the library, export, blah, blah, and finally you add it to the stage or container. It would be like this:

var wrap = $("div#wrap"),
    blobString = '<div class="blob"></div>',
    blobNumber = 10;//how many blobs you want in the wrap

for(var i = 0; i < blobNumber; i++)
{
    wrap.append(blobString);
}

Hope this helps,

Rodrigo.

Link to comment
Share on other sites

Hi Rodrigo,
I thank you very much for this solution. I did know that there are more than one blob element in the var blob (all with class blob) but I didn't know how to compare these elements in the for loop. so this is the trick: var blobAmount = blob.length;
and the other thing was to connect the several blobs with element via: var element = blob;
Again I thank you;

for me a very important step.
Michael

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