Meditation on JavaScript’s SetTimeout(), Recursion, and Execution Context

JavaScript’s setTimout and setInterval functions are for scheduling future work. They provide a way to schedule either a single or recurring execution of a function. In this article, we’ll play around with some fun and interesting capabilities that can be had using setTimeout.

To get going we’ll need a few examples in place.

Here is a a simple Calculator object that we can use for our testing. Note that it has 2 methods (add and multiply). It also contains a piece of state (value) that it uses to track its computational output.

//an object with methods
function Calculator (seed) {
    return {
          value: seed,
          add: function(b) {
            value = value || 0; //guard with default accumulator for addition
            this.value += b;
            console.log(this.value);
            return this;
          },
          multiply: function(b) {
            value = value || 1; //guard with default accumulator for multiplication
            this.value *= b;
            console.log(this.value);
            return this;
          }
    };
}
var calculator = new Calculator();

//basic math fluency
var twentyFive = calculator.add(1 + 1)
                           .add(3)
                           .multiply(5)
                           .value;

Now, let’s have some fun by giving all JavaScript objects in the runtime the ability to defer their own method execution until a time in the future. We do this by extending the Object prototype for the whole JavaScript runtime.

This implementation is as follows. Note that, that it imbues all objects with a new ability, to run future functions with themselves as the reciever.

if (typeof Object.prototype.later !== 'function') {
	Object.prototype.later = function (msec, method) {
		var that = this,
			args = Array.prototype.slice.apply(arguments, [2]);
		if (typeof method === 'string') {
			method = that[method];
		}
		setTimeout(function() {
			method.apply(that, args);
		}, msec);
		return that;
	};
}

Source: Douglas Crockford.

This in effect shims all objects with an additional behavior called “later”. It changes the receiver of the function call in the future to the object from which later() was invoked.

The function expects these things:

Parameter 1: The number of milliseconds to wait before executing

Parameter 2: Either a function or a string function name to execute

Additional Optional Parameters: The arguments for the method to be executed in the future

The later method takes in the parameters and schedules the function (parameter 2) with its arguments (parameters 3,4,5,…) to be executed in the specified milliseconds (parameter 1). Note that we use a closure to refer to the receiver (“this”) as “that” during the setup and scheduling phase of its execution. This ensures that the “this” inside of scope of execution is the object from which the .later() method is called. This overrides the pointer in setTimeout() for “this” from the default “global” JavaScript object to the object from which later() is invoked. This simple but elegant replacing of the execution context object is perhaps one of the most powerful features of JavaScript. Now that we’ve got this extension to the Object prototype in place, all objects in our system, including Calculator will have this behavior.

So let’s have some fun with the calculator by exercising the Chaining API it inherited from Object. Here are some tricks taking advantage of the fluent later() method’s ability to drive a series of asynchronous calls over the object from which the expression chain originates. Since calculator’s prototype is Object, it can drive its own api. This example demonstrates several different ways to invoke the later() method in a single expression chain. Let’s turn a calculator into an adding machine.

calculator
	//can pass a method name as a string.  targeting calculator.add
	.later(100, "add", 1)

	//can pass a method reference directly from the object
	.later(1000, calculator.add, 1)

	//can pass an anonymous function.
	.later(100, function(argument) {
		this.value += argument;
	}, 1)

    //close back onto chain originator
    .later(999, function(argument) { calculator.value += argument; }, 1);

//start an async message loop
calculator.later(0, function loop(argument) {
    this.value += argument;
    console.log(this.value);
    this.later(0, loop, argument);
}, "Looping");

Now lets have some fun with arrays.  Since JavaScript arrays inherit their prototype from Object, and we extended Object’s prototype with the later() method, arrays now also have the later() method.

Process an Array Asychronously:

var sequence = [1,2,3,4,5];
sequence.forEach(function(n) {
    sequence.later(0, function(i) {
    	console.log("got: " + i);
    }, n);
});

This is cool..

Now lets replace the execution context object with a new Calculator.

Driving Execution Over an Array – Compute Factorial:

[1,2,3,4,5].forEach(function(n) {
    return this.multiply(n).value;
}, new Calculator());

Lets Add Laterness:

//scheduled execution
[1,2,3,4,5].forEach(function(n) {
    this.later(100, this.multiply, n);
}, new Calculator());

Decaying Scheduled Array Processing:

[1,2,3,4,5].forEach(function(n) {
    this.wait = (this.wait || 0) + 1000 ;
    this.later(this.wait, this.multiply, n);
}, new Calculator());

Randomly Scheduled Array Processing:

[1,2,3,4,5].forEach(function(n) {
    this.later(Math.floor((Math.random()*1000)+1), this.multiply, n);
}, new Calculator());

Namaste…

Making Parallax Animation Effects With JavaScript

The Term “Parallax” means a difference in the apparent position of an object viewed along two different lines of sight, and is measured by the angle of inclination between those two lines. The positional difference between objects creates a visual illusion that is specific to the position of the observer.  A simple everyday example of parallax can be seen in the dashboard of motor vehicles that use a needle-style speedometer gauge.  When viewed from directly in front, the speed may show exactly 60; but when viewed from the passenger seat the needle may appear to show a slightly different speed, due to the angle of viewing.  This effect can be exploited when presenting content to trick the eyes into seeing multiple forced perspectives in the same scene.  When animated, the effects become visually interesting to people. Recently, I began a series of experiments to learn how parallax works.  In this article, I’ll walk you through the basics and leave you with a working example of a parallax web banner.  The code in this writeup, is available here.

First, let’s layout what we want to accomplish.

  • Mountains (far texture) – We want to build a scene that uses a scrolling landscape to provide the feeling of panning or having it spin around you.  (Note that I’ve modified this image to seamlessly scroll.  Here’s the technique ref.)
  • Sun (back texture) – We want to have a sun fixed in the sky in a position similar to the direction that the light in the landscape is coming from.
  • Cloud (mid texture) – We want to have clouds moving across our sky.
  • Girl (close texture) – We want a central figure of a person (our girl) at the front to hold our users’ attention and give the illusion that she’s in the scene.

Preview Results:

Parallax In Action Screenshot
Screenshot

We’ll begin with these 4 images.  Each is considered a texture that will be layered onto our stage, which in this case will be an HTML5 Canvas. With these images in our project, we can now write the code to bring them together and animate the scene.

Textures
Texture Images To Be Used As Sprites

First, we’ll make our markup. This is a minimal HTML file, with only a canvas element that will serve as our rendering stage for the scene.

<html>
  <head>
    <link rel='stylesheet' type='text/css' href='https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css' />
    <link rel='stylesheet' type='text/css' href='style.css' />
  </head>
  <body onload="init();">
  	<script src="pixi.js"></script>
    <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
	  <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
    
    <script type='text/javascript' src='script.js'></script>

    <div id=container; align="center">
      <p id="caption">
        Its A Beautiful World
      </p>
      <canvas id="game-canvas" width="1024" height="512"></canvas>
    </div>
  </body>
</html>

Next, we’ll write the JavaScript to bring it to life.

function init(){

  var WIDTH = 1024;
  var HEIGHT = 512;
  var stage = new PIXI.Stage();

  // let pixi choose WebGL or canvas
  var renderer;
  var back, far, mid, close;

  // target render to something on dom
  renderer = PIXI.autoDetectRenderer(WIDTH, HEIGHT, document.getElementById("game-canvas"));

  //sun texture
  var backTexture = PIXI.Texture.fromImage("sun1.gif");
  back = new PIXI.Sprite(backTexture, WIDTH, HEIGHT);
  back.position.x = 20;
  back.position.y = 7;

  //mountain texture
  var farTexture = PIXI.Texture.fromImage("mountain-04.jpg");
  far = new PIXI.TilingSprite(farTexture, WIDTH, HEIGHT);
  far.position.x = 0;
  far.position.y = 0;
  far.tilePosition.x = 0;
  far.tilePosition.y = 0;

  //cloud texture
  var midTexture = PIXI.Texture.fromImage("cloud1.gif");
  mid = new PIXI.Sprite(midTexture, WIDTH, HEIGHT);
  mid.position.x = WIDTH - 40;
  mid.position.y = -10;

  //girl texture
  var closeTexture = PIXI.Texture.fromImage("girl_character.gif");
  close = new PIXI.Sprite(closeTexture, WIDTH, HEIGHT);
  close.position.x = 512 - 256;
  close.position.y = 15;

  //add textures to stage in order from back to front
  stage.addChild(far);
  stage.addChild(back);
  stage.addChild(mid);
  stage.addChild(close);

  //render stage
  renderer.render(stage);

  //start animation loop
  requestAnimFrame(update);

  //recursive animation looper
  function update() {

    //move the far sprite to the left slowly
    far.tilePosition.x -= 0.128;

    //move the mid sprite to the left a little faster
    mid.position.x -= 0.37;
    if (mid.position.x < 0 - 512)
      mid.position.x = WIDTH + 512;

    renderer.render(stage);

    requestAnimFrame(update);
  }
}

Note that I’ve commented each stanza in this script to help you understand what’s happening. The code flow is generally this:

  1. Set dimensions for the stage (HEIGHT/WIDTH variables)
  2. Instantiate the stage.
  3. Instantiate a renderer targeted to the canvas element in the DOM
  4. Create sprites for the textures. Note that the far texture is a TilingSprite, so it’s position is manipulated by using the tilePosition attribute instead of the position attribute like the regular sprites.
  5. Place the stage into the renderer.
  6. Then finally, we start the animation loop by feeding the recursive update callback to the requestAnimFrame function given to us by PIXI. A more thorough look at the update function is required:

    1. Since we want the far texture to scroll to the left slowly, we decrement by .128px its position on the x axis each time the update function is called.
    2. Since we want the mid texture to scroll to the left more quickly, we decrement by .37px (a larger number) its position on the x axis each time the update function is called.

When brought together, the effects can be visually interesting. I say interesting, because the effect can be pleasant or disorienting depending upon how you’ve positioned the sprites and how quickly they are moving. The basic approach that I’m showing here can be used as the foundation for side-scrolling video games. There are also many potential uses for Web Banners, Presentations, Data Visualization, Rich User Interfaces, and more.

Result:

Hopefully you find this useful, or if nothing else instructive. You can get my code here

Namaste..