Alan
Alan

Reputation: 2086

How to avoid eval() when looping through array?

I am working with Greensock animation library and when building a sequential animation (where one thing ends and the next starts right away) you have to enter it like this:

childTL.to($box, 1, {x:50,y:0})
       .to($box, 1, {x:50,y:50})
       .to($box, 1, {x:-50,y:50})
       .to($box, 1, {x:-50,y:0});  

The issue I have is that I am storing all the things in a database or as variables and so need to build things incrementally using for loops.

What I want is something like this:

var animation = {
  "name": "movearound",
  "sequence": [{
    "duration": "1",
    "vars": {
      "x": "50",
      "y": "0"
    }
  }, {
    "duration": "1",
    "vars": {
      "x": "50",
      "y": "0"
    }
  }, {
    "duration": "1",
    "vars": {
      "x": "50",
      "y": "0"
    }
  }, {
    "duration": "1",
    "vars": {
      "x": "50",
      "y": "0"
    }
  }]
}
target = $(".target123")
childTL = new TimelineLite{onUpdate: updateSlider});

for (S = 0; S < animatelayers.sequence.length; S++) {
  duration = animatelayers.sequence[S]["duration"];
  sequence = animatelayers.sequence[S]["vars"];
  if (S == 0) {

    childTL.to(target, duration, sequence)
  } else {
    .to(".target", duration, sequence);
  }
}

I know I could do it with concatenating strings together and then do an eval() on it, but is there a way to do it without?

Edit for why I am talking about eval():

I guess the trouble I have is how picky Greensock is when it comes to things coming in as strings vs objects - for example you can use $("#target") in the .to(), but you can't use it if you define it as a variable first var target = $("#target"); and then childTL.to(target, 1, {x:50,y:0}) would fail, but if you do it as var target = "#target" it would work. So in the past I had created it all exactly like Greensock wanted as a string, and then used eval(). While I can keep doing that, I prefer to look for better ways of accomplishing things.

Upvotes: 0

Views: 60

Answers (1)

melpomene
melpomene

Reputation: 85767

Your sample code makes no sense, so instead I'm going to demonstrate how to convert your original snippet to use a data structure and a loop:

childTL.to($box, 1, {x:50,y:0})
       .to($box, 1, {x:50,y:50})
       .to($box, 1, {x:-50,y:50})
       .to($box, 1, {x:-50,y:0});

First we define our data:

var coords = [
    {x: 50, y: 0},
    {x: 50, y:50},
    {x:-50, y:50},
    {x:-50, y: 0}
];

Then we loop:

var obj = childTL;
for (var i = 0; i < coords.length; i++) {
    obj = obj.to($box, 1, coords[i]);
}

This is a strict conversion of the original chained .to(...).to(...).to(...) calls. However, doing things this way isn't actually necessary. The .to method simply returns the object for convenience (according to https://greensock.com/docs/#/HTML5/Animation/TimelineLite/to/); you don't have to use it.

You can simply say:

for (var i = 0; i < coords.length; i++) {
    childTL.to($box, 1, coords[i]);
}

Upvotes: 1

Related Questions