好きなだけかりんとうを食べる人生

フロントエンドとかデザインとかバックエンドとか浅く広く。社会人3年目のうぇぶでぃれくたーです。

canvasでホタルを描いてみた

canvas使ってる色々なサンプル眺めてたら作ってみたくなりました。
夜、明かりを消してディスプレイを見た時(目に良くないけど)、画面いっぱいにホタルが舞ってたらなんとなく癒やされるなーなんて。

ライブラリやフレームワークを使わず、純粋なJavascriptとhtmlのみで実装してみました(リセット用のCSSは使ってます)。
canvas使っているのでIE7,IE8とかは見れないと思います〜。アプデしてね。

サンプル

サンプル

コード

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

// 定数の宣言
var FPS = 60;
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var HOTARU_NUM = 80;

// 変数の宣言
var hotaruArr = [];
var ctx;

window.onload = function() {
  init();
};

// 初期化
var init = function() {

  var cvs = document.getElementById('canvas');
  cvs.width = SCREEN_WIDTH;
  cvs.height = SCREEN_HEIGHT;
  ctx = cvs.getContext('2d');
  createHotaru();
  loop();

};

// インスタンスの生成
var createHotaru = function() {

  for (var i = 0; i < HOTARU_NUM; i++) {
    var hotaru = new Hotaru();
    hotaru.setConfig();
    hotaruArr.push(hotaru);
  };

};

// 各要素を描画
var draw = function() {

  ctx.fillStyle = 'rgb(0, 0, 0)';
  ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

  for (var i = 0; i < hotaruArr.length; i++) {
    hotaruArr[i].drawHotaru();
  }

};

// 位置の更新
var update = function() {

  for (var i = 0; i < hotaruArr.length; i++) {
    hotaruArr[i].updateHotaru();
  }

};

// 描画・更新のループ
var loop = function() {

  draw();
  update();
  setTimeout(loop, 1000 / FPS);

};

// オブジェクトのコンストラクタ
var Hotaru = function() {};

// メソッド・プロパティ
Hotaru.prototype = {

  setConfig: function() {

    this.posX = Math.random() * SCREEN_WIDTH;
    this.posY = Math.random() * SCREEN_HEIGHT;
    this.mX = Math.random() * 0.5 - 0.25;
    this.mY = Math.random() * 0.5 - 0.25;
    this.r = Math.random() * 5 + 2;
    this.rdm = Math.floor(Math.random() * 360);
    this.alpha = 1.0;
    this.color = 'rgba(202, 251, 74,' + this.alpha + ')';

  },

  // プロパティに対応したオブジェクトを描画
  drawHotaru: function() {

    ctx.beginPath();
    ctx.fillStyle = this.color;
    ctx.arc(this.posX, this.posY, this.r, 0, Math.PI * 2, false);
    ctx.fill();

  },

  // オブジェクトの更新
  updateHotaru: function() {

    if (this.posX < 0 - this.r) {
      this.posX = SCREEN_WIDTH + this.r;
    } else if (this.posX > SCREEN_WIDTH + this.r) {
      this.posX = 0 - this.r;
    }
    if (this.posY < 0) {
      this.posY = SCREEN_HEIGHT + this.r;
    } else if (this.posY > SCREEN_HEIGHT) {
      this.pos = 0 - this.r;
    }

    this.posX += this.mX;
    this.posY += this.mY;
    this.rdm += 1.2;
    this.alpha = Math.abs(Math.cos(this.rdm * Math.PI / 180) * 0.5 + 0.5);
    this.color = 'rgba(202, 251, 74,' + this.alpha + ')';

  }

};

時間がかかった部分

ホタルの光を表現しようとした時、点滅する動作をどう表現しようか悩みました。
単純に増減させるだけでは機械的になっちゃいますし。 なんとなーく2次曲線ぽく表現したかったんですよ。なめらかに点滅する感じで。
そこで三角関数を使うことにしました。

this.alpha = Math.abs(Math.cos(this.rdm * Math.PI / 180) * 0.5 + 0.5);

この部分ですね。

まとめ

今回の制作で、canvasの基本や、オブジェクト指向に(なるべく)則った(つもりである)コードの書き方がなんとなく掴めてきた気がします。

次は花火とか面白そうだな〜なんて思ってます。