Jump to content
Search Community

Call a function per item?

Gary test
Moderator Tag

Go to solution Solved by Gary,

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

Does GSAP have any intrinsic support for calling a function to get a vars value?   Given an array of divs and an array of data, with one datum per div, it could look up a property value.  


For example:


var data = [[20,50],[25,41],[22,10]];


function getX(index) { return data[index][0]; }

function getY(index) { return data[index][1]; }


tl.staggerTo(divs, 5, {left:getX, top:getY}, 1);



I don't think it does, but thought it was worth asking.  If not, might be a nice future enhancement.



Link to comment
Share on other sites

Well, yes and no. Yes, it does support calling a function as a getter/setter on an object, like:

var obj = {
    getX: function() {
        return this._x;
    setX: function(value) {
        this._x = value;
        //do other stuff...
//then later...
TweenLite.to(obj, 1, {setX:100});

That'll automatically see that "setX" is a method rather than a property, and since it starts with "set", it'll look for the "get" version of it as the getter (in this case "getX()". So it'll end up getting the current value with obj.getX() and then animate that to 100 and apply it with obj.setX() on every update. 


That'll also work with single-method getters/setters like the jQuery-style ones, where if you don't pass a parameter, it acts as a getter and if you do pass a parameter, it acts as a setter. In fact, that's why you can tween a tween or timeline like:

var tween = TweenLite.to(...);
TweenLite.to(tween, 2, {progress:1}); //literally tweens the progress() of the other tween!

That's because progress() is one of those methods that's both a getter and setter. Same with time() and totalTime() and timeScale(), etc. Mind-bending, right? :)


In your case, I think it'd actually perform a bit better if you simply did it like this:

var data = [[20,50],[25,41],[22,10]],
    time = tl.duration(),

for (i = 0; i < divs.length; i++) {
    time += 1; //stagger
    tl.to(divs[i], 5, {left:data[i][0], top:data[i][1]}, time);

Does that help?

  • Like 2
Link to comment
Share on other sites

  • Solution

Yup, that helps.  The object methods is really good to know.  I don't need it yet, but it looks very useful.


The hand-rolled loop is what I am doing now and it works great.  I've been using D3.js a lot and have become a fan of the loop-less data interaction with modular data processing functions.  For instance, random values like this would be trivial.


function randomNumber(min, max){
  return Math.floor(Math.random() * (1 + max - min) + min);

tl.to(divs, 5, {x:randomNumber.bind(0,100)});


Writing explicit loops works perfectly fine.  The above approach is merely semantic sugar.  Thought I'd ask because I have a sweet tooth. :)

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.
  • Create New...