Object Variables

There’s a feature that was added to GLC a while back, which I realize I never properly explained.

When you create a shape, you pass in an object that contains various pre-defined properties that define how the shape is drawn. But, you can actually add other properties to that object as well – any property you want. Then, if you have a function defining a property, you can access that custom property by use of the keyword, this. For example:

list.addCircle({
centerX: width / 2,
centerY: height / 2,
x: function(t) {
return this.centerX + Math.cos(t * Math.PI * 2) * 100;
},
y: function(t) {
return this.centerY + Math.sin(t * Math.PI * 2) * 100;
},
radius: 10
});

Here, I’ve defined a centerX and centerY property on the object, and accessed that within the functions that define x and y. That’s a simple example to show how object variables work, but it doesn’t really show off how they can be useful. In this case, centerX and centerY could easily have just been regular variables anywhere in that code. So let’s take another example.


for(var i = 0; i < 6; i++) { var angle = Math.PI * 2 / 6 * i; list.addCircle({ x: width / 2 + Math.cos(angle) * 100, y: height / 2 + Math.sin(angle) * 100, radius: 10 }); }

Here we have a for loop creating six circles. It first creates an angle variable based on the for loop variable, i. It then uses that variable to calculate the x and y position of each circle. This gives us this image:

thistest01

Now let's change that just a bit.


for(var i = 0; i < 6; i++) { var angle = Math.PI * 2 / 6 * i; list.addCircle({ x: function(t) { return width / 2 + Math.cos(angle) * 100; }, y: function(t) { return height / 2 + Math.sin(angle) * 100; }, radius: 10 }); }

I didn't change the formula for x and y at all. I just wrapped them in functions. But when we do this, we get this picture:

thistest02

What happened?

OK, in the first example, we were calculating that formula, width / 2 + Math.cos(angle) * 100, right in the for loop, getting the number that evaluated to, and assigning it to x. And the same for y.

In the second example, we were NOT evaluating that formula in the for loop. It was just going into the function. You have to think of this in terms of time.

First, the for loop runs, creating all the circle objects. Inside of that, the variable, i, is going from 0 up to 5, and the angle variable on each iteration is:


0
1.0471975511965976
2.0943951023931953
3.141592653589793
4.1887902047863905
5.235987755982988

But that angle variable is never actually accessed during the for loop. When the for loop finishes, angle = 5.23598... And that's where it stays. All of this happens before you ever see a single thing on the screen.

Then, well after that for loop has completed, GLC starts looping. It goes through each circle object and when it sees that they have functions for x and y, it calls those functions. When the functions run, they access the current value of angle, which, as we just saw, is now stuck at 5.23598... radians, or 300 degrees. And that's where each circle gets drawn.

This is the exact situation that object variables are designed to solve. We change the code to this:


for(var i = 0; i < 6; i++) { var angle = Math.PI * 2 / 6 * i; list.addCircle({ a: angle, x: function(t) { return width / 2 + Math.cos(this.a) * 100; }, y: function(t) { return height / 2 + Math.sin(this.a) * 100; }, radius: 10 }); }

Here, I've created an a property on the object. This gets assigned the current value of angle inside that for loop. So the first circle gets 0 for a. On the next iteration, angle is 1.047... but that doesn't change the a value for the first circle. The second circle gets 1.047 as its a though. And so on for the rest of the circles. Now each circle has a unique value for a that is locked in. And this brings us back to our original picture.

thistest01

Now of course, at this point I'd go in and add to that formula to make some custom animation using t, such as:


for(var i = 0; i < 6; i++) { var angle = Math.PI * 2 / 6 * i; list.addCircle({ a: angle, x: function(t) { return width / 2 + Math.cos(this.a) * 100 + t * 50; }, y: function(t) { return height / 2 + Math.sin(this.a) * 100 + t * 50; }, radius: 10 }); }

Not the most exciting animation, but hopefully this helps.

Leave a Reply