Question

The Situation

I need to loop through an array, and run a tween based on each item's value. Thus, for each item in the array, there must be a separate Tween instance. According to the TweenJS documentation, the get() method "Returns a new tween instance".

The Problem

It appears as though there is only a single instance when running a new tween for each item in the array inside a for loop

The Code

HTML

<div id='log'></div>

Javascript

var items = [3,6,2,8,9,6];
var log = document.getElementById('log');

for(var i = 0; i < items.length; i++){
    var item = items[i];

    var start = {
        x: item * 10,
        y: item * 15
    };

    var end = {
        x: item * 10,
        y: item * 30
    };

    createjs.Tween
        .get(start, {
            onChange: function () {
                log.innerHTML = log.innerHTML + i + " - " +  JSON.stringify(start) + "<br/>";
            }
        })
        .to(end, 1000)
};

The Demo

http://codepen.io/anon/pen/pilAL - Notice the output. The number at the beginning is the index of the current array's value. It only shows the last item.

Ideally...

Ideally, each item in the array would tween separately between its values.

Thanks in advance!

Was it helpful?

Solution

The quick-and-dirty solution is to use the "event" argument in onChange, and inspect its target.target property.

The trick is that it is properly firing for everything, but the variable scoping is such that i and start no longer contain the values you seek by the time the event method fires.

Here it is with that change: http://codepen.io/anon/pen/FhsHz

Aye, as I expected, it's coming from a lexical scoping issue... I had to refresh myself on it, as it's a while since I've had to deal with Javascript in such a way (and thus worry about it!)

Read through this guide, it's very insightful and starts to address your issue and ways to work around it in the subsection "Creating closures in loops":

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures

The gist is that, if you want that anonymous function you create to use the values captured upon creation of the function, you have to get the scoping of the variable you end up using into such a state that it actually is pointing to the desired value.

It's annoying, and they really should provide a more intuitive parameter to you than "event.target.target" as a place to get the value you seek, but the alternative to that is to do something like what they do in this example and essentially make a function generating function, into which you pass the variable. At that point, the scope of the variable that the function uses becomes the scope of the passed-in argument in the "generating function", and it will be pointing to the proper value. Y u c k.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top