HTML5のCanvasでつくるダイナミックな表現―CreateJSを使う

第11回 マウスポインタの動きに合わせてインスタンスをランダムに落とす

この記事を読むのに必要な時間:およそ 7 分

インスタンスの動きに水平方向の初速を加える

落ちるインスタンスの動きに,水平方向の初速も加えよう。簡単なのは,水平方向にもランダムな速度を定めることだ。しかし,今回ランダムな速度はひとつにする。その代わり,ランダムな角度を加える。速度と角度から水平・垂直それぞれの値を決めるのだ。そのためには,三角関数を用いる。

原点O(0, 0)を中心に描いた半径1の円(⁠⁠単位円」と呼ぶ)について,原点Oからx軸正方向に対して角度θの直線と交わる点Pのxy座標は三角関数により(cosθ, sinθ)と定められている図4⁠。つまり,原点からの距離は1で角度がθの点のxy座標は(cosθ, sinθ)ということだ。すると,原点からの距離がrなら,座標は(r cosθ, r sinθ)になる。

図4 原点から距離が1で角度θのxy座標は(cosθ, sinθ)

図4 原点から距離が1で角度θのxy座標は(cosθ, sinθ)

この距離rを速さと見立てれば,角度θを与えたときのxy各軸方向の速度が導ける。そこで,以下のインスタンスをつくる関数(createInstance())は,0から2πラジアン(360度)までのランダムな角度(angle)を求め,水平・垂直方向の初速をプロパティ(velocityXとvelocityY)として与えるように書替えた。

また,アニメーションの関数(animate())には,水平方向の動きを加えた。水平には重力は働かないので,基本は等速運動だ。ただ,摩擦などによる減速を表すため,定数(0.98)を乗じた。

function createInstance(x, y, halfSpeed) {
  var speed = getRandom(-halfSpeed, halfSpeed);
  var angle = getRandom(0, Math.PI * 2);
  var instance = createShape(2, 10);

  instance.velocityX = Math.cos(angle) * speed;
  // instance.velocityY = speed;
  instance.velocityY = Math.sin(angle) * speed; 

}
function animate(eventObject) {
  var count = stage.getNumChildren() - 1;
  for (var i = count; i > -1; i--) {
    var child = stage.getChildAt(i);
    var newY = child.y + child.velocityY;

      child.x += child.velocityX;
      child.y = newY;

      child.velocityX *= 0.98;
      child.velocityY += 2;

  }

}

これでマウスポインタの動く位置に表れるインスタンスに,ランダムな方向の初速が与えられる図5⁠。垂直方向には重力加速度が加わりつつ,水平移動は少しずつ減速する。書替えたJavaScript全体は,つぎのコード2のとおりだ。

図5 マウスポインタの動く位置に表れたインスタンスにランダムな方向の初速が与えられる

図5 マウスポインタの動く位置に表れたインスタンスにランダムな方向の初速が与えられる

コード2マウスポインタの動きに合わせて表れたインスタンスがランダムな方向に落ちる

var stage;
var stageHeight;
function initialize() {
  var canvasElement = document.getElementById("myCanvas");
  stageHeight = canvasElement.height;
  stage = new createjs.Stage(canvasElement);
  stage.addEventListener("stagemousemove", addInstance);
  createjs.Ticker.addEventListener("tick", animate);
}
function addInstance(eventObject) {
  createInstance(stage.mouseX, stage.mouseY, 15);
  stage.update();
}
function createInstance(x, y, halfSpeed) {
  var speed = getRandom(-halfSpeed, halfSpeed);
  var angle = getRandom(0, Math.PI * 2);
  var instance = createShape(2, 10);
  instance.x = x;
  instance.y = y;
  instance.velocityX = Math.cos(angle) * speed;
  instance.velocityY = Math.sin(angle) * speed;
  instance.velocityAlpha = getRandom(-0.07, -0.01);
  stage.addChild(instance);
}
function animate(eventObject) {
  var count = stage.getNumChildren() - 1;
  for (var i = count; i > -1; i--) {
    var child = stage.getChildAt(i);
    var newY = child.y + child.velocityY;
    var newAlpha = child.alpha + child.velocityAlpha;
    if (newAlpha <= 0 || newY > stageHeight) {
      stage.removeChildAt(i);
    } else {
      child.x += child.velocityX;
      child.y = newY;
      child.alpha = newAlpha;
      child.velocityX *= 0.98;
      child.velocityY += 2;
    }
  }
  stage.update();
}
function createShape(min, max) {
  var instance = new createjs.Shape();
  var radius = getRandom(min, max);
  var color = Math.floor(Math.random() * 0xFFFFFF);
  instance.graphics.beginFill(createjs.Graphics.getRGB(color))
  .drawCircle(0, 0, radius);
  return instance;
}
function getRandom(min, max) {
  var randomNumber = Math.random() * (max - min) + min;
  return randomNumber;
}

前掲コード2をjsdo.itにサンプルコードとして掲げた。今回は,ここまでにしておこう。次回は少し目先を変えてスプライトシートアニメーションについて解説したうえで,今回の弾けるインタラクティブなアニメーションのコードに組み込んでみる。

著者プロフィール

野中文雄(のなかふみお)

ソフトウェアトレーナー,テクニカルライター,オーサリングエンジニア。上智大学法学部卒,慶応義塾大学大学院経営管理研究科修士課程修了(MBA)。独立系パソコン販売会社で,総務・人事,企画,外資系企業担当営業などに携わる。その後,マルチメディアコンテンツ制作会社に転職。ソフトウェアトレーニング,コンテンツ制作などの業務を担当する。2001年11月に独立。Web制作者に向けた情報発信プロジェクトF-siteにも参加する。株式会社ロクナナ取締役(非常勤)。

URLhttp://www.FumioNonaka.com/

著書