さぁ!検索しよう!

JavaScriptでcanvas上にビルを描画する方法です。

DEMO

HTML

<canvas id="canvas"></canvas>

CSS

body{
  background:darkblue;
  margin:0;
  overflow:hidden;
  padding:0;
}

JavaScript

(function() {
  var canvas = document.getElementById('canvas');
  var windowWidth = window.innerWidth;
  var windowHeight = window.innerHeight;
  canvas.width = windowWidth;
  canvas.height = windowHeight;
  var ctx = canvas.getContext('2d');
  var building;
  var bWindow = {
    width: 20,
    height: 20,
    offset: 20
  }
  var Building = function(x, w, h, c) {
    this.width = w;
    this.height = h;
    this.x = x;
    this.y = windowHeight - h;
    this.color = c;
  }
  Building.prototype.drawBuilding = function() {
    ctx.fillStyle = this.color;
    ctx.fillRect(this.x, this.y, this.width, this.height);
    this.drawWindow();
  }
  Building.prototype.drawWindow = function() {
    var windowCol = Math.floor((this.width - bWindow.offset) / (bWindow.width + bWindow.offset));
    var windowRow = Math.floor((this.height - bWindow.offset) / (bWindow.height + bWindow.offset));
    for (var i = 1; i < windowCol; i++) {
      for (var j = 1; j < windowRow; j++) {
        ctx.fillStyle = "yellow";
        ctx.fillRect(this.x + i * (bWindow.width + bWindow.offset), this.y + j * (bWindow.height + bWindow.offset), bWindow.width, bWindow.height);
      }
    }
  }
  Building.prototype.onresize = function() {
    var bHeight = this.height;
    this.y = windowHeight - bHeight;
  }

  document.addEventListener('DOMContentLoaded', function() {
    init();
  }, false);

  function init() {
    canvas.width = windowWidth;
    canvas.height = windowHeight;
    building = new Building(50, 200, 300, "#333333");
    render();
  }

  function render() {
    ctx.clearRect(0, 0, windowWidth, windowHeight);
    building.drawBuilding();
    window.requestAnimationFrame(render);
  }

  function onResize() {
    windowWidth = window.innerWidth;
    windowHeight = window.innerHeight;
    canvas.width = windowWidth;
    canvas.height = windowHeight;
    building.onresize();
  }

  window.addEventListener('resize', onResize, false);
})();

JavaScriptのポイントは以下の通りです。

窓の情報を定義

bWindowは、窓の一つのサイズと周りの余白を定義しています。

var bWindow = {
        width: 20,
    height: 20,
        offset: 20
}

ビルの情報を定義

Buildingは、ビルの情報を定義しています。

var Building = function(x, w, h, c) {
    this.width = w;
    this.height = h;
    this.x = x;
    this.y = windowHeight - h;
    this.color = c;
 }

Buildingの引数については以下の通りです。

|:—–:|:—–:|

引数
x 水平方向の位置
w 横幅
h 高さ
c カラー

ビルを描画

Building.prototype.drawBuildingで、ビル・窓を描画します。

Building.prototype.drawBuilding = function() {
    ctx.fillStyle = this.color;
    ctx.fillRect(this.x, this.y, this.width, this.height);
    this.drawWindow();
  }

窓を描画

Building.prototype.drawWindowで、窓を描画します。

Building.prototype.drawWindow = function() {
    var windowCol = Math.floor((this.width - bWindow.offset) / (bWindow.width + bWindow.offset));
    var windowRow = Math.floor((this.height - bWindow.offset) / (bWindow.height + bWindow.offset));
    for (var i = 1; i < windowCol; i++) {
      for (var j = 1; j < windowRow; j++) {
        ctx.fillStyle = "yellow";
        ctx.fillRect(this.x + i * (bWindow.width + bWindow.offset), this.y + j * (bWindow.height + bWindow.offset), bWindow.width, bWindow.height);
      }
    }
  }

処理の流れは下記の通りです。

  1. windowColは、水平方向へ窓を描画させるためのスペースを確保しており、ビルの右端の余白を残すために、ビルの横幅から余白を引いた値を窓の横幅+余白で割っています。
    windowRowも同様です。

        var windowCol = Math.floor((this.width - bWindow.offset) / (bWindow.width + bWindow.offset));
        var windowRow = Math.floor((this.height - bWindow.offset) / (bWindow.height + bWindow.offset));
        
  2. for文を入れ子にし、this.xthis.yに窓の横(縦)幅+余白をiだけ加え、窓を一気に描画しています。

        for (var i = 1; i < windowCol; i++) {
              for (var j = 1; j < windowRow; j++) {
                ctx.fillStyle = "yellow";
                ctx.fillRect(this.x + i * (bWindow.width + bWindow.offset), this.y + j * (bWindow.height + bWindow.offset), bWindow.width, bWindow.height);
              }
            }
        

    for文を入れ子にした処理の仕組みはこちらをご覧ください。

Building.prototype.onresizeは、ブラウザウィンドウのサイズが変化したときに実行される関数です。

ブラウザウィンドウのサイズが変更されたときの高さを取得し、それをwindowHeightから引くことで、常に下端に配置されるようにしています。

Building.prototype.onresize = function() {
    var bHeight = this.height;
    this.y = windowHeight - bHeight;
  }

init()は初期化する関数であり、DOMContentLoadedで、HTMLの読み込みが完了したときに実行されます。

function init() {
    canvas.width = windowWidth;
    canvas.height = windowHeight;
    building = new Building(50, 200, 300, "#333333");
    render();
  }

処理の流れは下記の通りです。

  1. ブラウザウィンドウの内側の幅・高さをcanvasの幅・高さとします。

        canvas.width = windowWidth;
        canvas.height = windowHeight;
        
  2. ビルのクラスをインスタンス化しています。

         building = new Building(50, 200, 300, "#333333");
        
  3. render()を実行しています。

        render();
        

render()は、onresizeが実行されたときに、ビルの描画や位置を再調整する関数です。

 function render() {
    ctx.clearRect(0, 0, windowWidth, windowHeight);
    building.drawBuilding();
    window.requestAnimationFrame(render);
  }

以上で、canvas上にビル群を描画する方法を終わります。