2
\$\begingroup\$

I have created a utility to create scrolling parallax backgrounds.

// Backgrounds as array of objects. canvas id, speed, image url
var bgs = [{
  id: 'sky',
  speed: 1,
  src: 'https://upload.wikimedia.org/wikipedia/commons/9/9f/Sky_back_layer.png'
}, {
  id: 'middle',
  speed: 3,
  src: 'https://upload.wikimedia.org/wikipedia/commons/8/8b/Vegetation_%28middle_layer%29.png'
}, {
  id: 'front',
  speed: 5,
  src: 'https://upload.wikimedia.org/wikipedia/commons/b/be/Ground_%28front_layer%29.png'
}];

// Create render background through Scenery
var Scenery = {
  bgs: [],
  // Initialize individual canvases and set images
  init: function(bgs) {
    var i = bgs.length - 1,j = 0;
    for (; i >= 0; i--,j++) {
      this.bgs[j] = {};
      this.bgs[j].cvs = document.getElementById(bgs[i].id);
      this.bgs[j].ctx = this.bgs[j].cvs.getContext('2d');
      this.bgs[j].img = document.createElement('img');
      this.bgs[j].img.src = bgs[i].src;
      this.bgs[j].left = 0;
      this.bgs[j].speed=bgs[i].speed;
    }
  },
  // According to scroll speed, render images in corresponding canvas
  // To have a seamless effect, render image twice
  scene: function() {
    var i = this.bgs.length - 1,
      left, w, h, bgNow, bgCtx;
    for (; i >= 0; i--) {
      bgNow = this.bgs[i];
      left = bgNow.left;
      w = bgNow.cvs.width;
      h = bgNow.cvs.height;
      bgCtx = bgNow.ctx;

      bgCtx.clearRect(0, 0, w, h);
      bgCtx.drawImage(this.bgs[i].img, -left, 0, w, h);
      bgCtx.drawImage(this.bgs[i].img, w - left, 0, w, h);
      this.bgs[i].left = (left + this.bgs[i].speed) % w;
    }

  }
};

// This handles looping . A wrapper around window.requestAnimationFrame
// Considers frame rate.
var Loop = {
  run: function(scene, fps) {
    this.scene = scene;
    this.frameInterval = 1000 / fps;
    this.lastTime = new Date().getTime();

    this.loop();
  },
  loop: function() {
    var now = new Date().getTime();
    var elapsed = now - this.lastTime;
    if (elapsed >= this.frameInterval) {

      this.scene();
      this.lastTime = now;
    }
    window.requestAnimationFrame(this.loop.bind(this));
  }
};

// Initialize scenery
Scenery.init(bgs);
// Run it
Loop.run(Scenery.scene.bind(Scenery), 60);

HTML

<div>
  <canvas id='sky'></canvas>
  <canvas id='middle'></canvas>
  <canvas id='front'></canvas>
</div>

Styles

div {
  position: relative;
}

canvas {
  position: absolute;
  left: 0;
  top: 0;
}

My question is, is there a better approach to pass Scenery.scene function into Loop.run()?

\$\endgroup\$

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.