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

第3回 Canvasの四辺をランダムなイージングで移動する

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

前回までのあらすじは,Canvasの左右をランダムな垂直位置と時間で行き来するトゥイーンができたところだった。今回は,いよいよお題の動きを仕上げる。ランダムなトゥイーンに,さらにふたつの要素を加えたい。ひとつは,イージングも複数の中からランダムに選びたい。もうひとつは,トゥイーンの行き先を左右の端だけでなく,Canvasの四辺に拡げる。そして,そのときランダムの偏りについて少しばかりこだわる。

イージングをランダムに変える

まず,前回つくった第2回コード2をおさらいとして掲げておく。ランダムなトゥイーンの設定を関数(setRandomTween())に定め,トゥイーンの終わりにTween.call()メソッドで呼出すことにより,新たなトゥイーンを始めている。ランダムに定めるのは,トゥイーンにかける時間と行き先の垂直座標だ。トゥイーンを始める端は左右交互に入れ替わるので,変数(currentSide)に覚えさせた。

第2回 コード2 ランダムな垂直位置と時間で左右を行き来するトゥイーンアニメーション(再掲)

var stage;
var myBitmap;
var top = 0;
var bottom;
var left = 0;
var right;
var currentSide;
function initialize() {
  canvasObject = document.getElementById("myCanvas");
  var file = "images/Pen.png";
  var loader = new createjs.LoadQueue(false);
  right = canvasObject.width;
  bottom = canvasObject.height;
  stage = new createjs.Stage(canvasObject);
  loader.addEventListener("fileload", draw);
  loader.loadFile(file);
}
function draw(eventObject) {
  var myImage = eventObject.result;
  var halfWidth = myImage.width / 2;
  var halfHeight = myImage.height / 2;
  top += halfHeight;
  bottom -= halfHeight;
  left += halfWidth;
  right -= halfWidth;
  myBitmap = new createjs.Bitmap(myImage);
  myBitmap.regX = halfWidth;
  myBitmap.regY = halfHeight;
  myBitmap.x = halfWidth;
  myBitmap.y = (top + bottom) / 2;
  stage.addChild(myBitmap);
  stage.update();
  setRandomTween(myBitmap, "left");
  createjs.Ticker.addEventListener("tick", stage);
}
function setRandomTween(target, side) {
  var nextPoint = getNextPosition(side);
  var randomTime = Math.random() * 5000 + 1000;
  setTween(target, nextPoint, randomTime, createjs.Ease.bounceOut);
}
function setTween(target, myPoint, time, easing) {
  createjs.Tween.get(target)
  .to({x:myPoint.x, y:myPoint.y}, time, easing)
  .call(setRandomTween, [target, currentSide]);
}
function getNextPosition(side) {
  var nextX;
  var nextY = Math.random() * (bottom - top) + top;
  if (side == "left") {
    currentSide = "right";
    nextX = right;
  } else {
    currentSide = "left";
    nextX = left;
  }
  return new createjs.Point(nextX, nextY);
}

ランダムに選ぶイージングは,もともと使っていたバウンドのEase.bounceOutに,滑らかな変化(circ)と弾力のある動き(elastic)を加える。イージングの与え方(In/Out/InOut)もそれぞれ変えることにして,Ease.circInEase.elasticInOutメソッドを選んだ。第1回にご紹介したTweenJSのページのデモSpark Tableで,3つのイージングの変化を比べてみたのがつぎの図1だ。

図1 バウンドと滑らかな変化および弾力のあるイージング

図1 バウンドと滑らかな変化および弾力のあるイージング

イージングの種類も数も,後で自由に変えられるようにしたい。すると,それらの参照を配列に入れて扱うのがお約束だ。そこで,つぎのように配列(easings)を定めた。すると,そのArray.lengthプロパティ値(エレメント数)未満の整数をランダムに求めて,そのインデックスのイージング(easing)を取出せばよい。

var easings = [createjs.Ease.circIn, createjs.Ease.bounceOut, createjs.Ease.elasticInOut];

function setRandomTween(target, side) {   var nextPoint = getNextPosition(side);   var randomTime = Math.random() * 5000 + 1000;   var easing = easings[Math.floor(Math.random() * easings.length)];   // setTween(target, nextPoint, randomTime, createjs.Ease.bounceOut);   setTween(target, nextPoint, randomTime, easing); }

さらに,次項でオブジェクトの動きをCanvasの四辺に拡げる。そのため,動く範囲の座標は,関数(setGeometricData())を分けて定めることにした。今のところ,やっている中身に変わりはない。

function draw(eventObject) {
  var myImage = eventObject.result;
  var halfWidth = myImage.width / 2;
  var halfHeight = myImage.height / 2;
  /*
  top += halfHeight;
  bottom -= halfHeight;
  left += halfWidth;
  right -= halfWidth;
  */
  setGeometricData(halfWidth, halfHeight);
  // ...[中略]...
}
function setGeometricData(offsetX, offsetY) {
  top += offsetY;
  bottom -= offsetY;
  left += offsetX;
  right -= offsetX;
}

第2回コード2にこれらの手を加えたのが,つぎのコード1だ。トゥイーンの時間と移動する垂直座標に加えて,イージングが前述の3つからランダムに選ばれる。イージングの配列(easings)の中身を変えれば,選択肢は自由に変えられる。

コード1 トゥイーンの時間と垂直位置およびイージングがランダムに左右を行き来するアニメーション

var stage;
var myBitmap;
var top = 0;
var bottom;
var left = 0;
var right;
var currentSide;
var easings = [createjs.Ease.circIn, createjs.Ease.bounceOut, createjs.Ease.elasticInOut];
function initialize() {
  canvasObject = document.getElementById("myCanvas");
  var file = "images/Pen.png";
  var loader = new createjs.LoadQueue(false);
  right = canvasObject.width;
  bottom = canvasObject.height;
  stage = new createjs.Stage(canvasObject);
  loader.addEventListener("fileload", draw);
  loader.loadFile(file);
}
function draw(eventObject) {
  var myImage = eventObject.result;
  var halfWidth = myImage.width / 2;
  var halfHeight = myImage.height / 2;
  setGeometricData(halfWidth, halfHeight);
  myBitmap = new createjs.Bitmap(myImage);
  myBitmap.regX = halfWidth;
  myBitmap.regY = halfHeight;
  myBitmap.x = halfWidth;
  myBitmap.y = (top + bottom) / 2;
  stage.addChild(myBitmap);
  stage.update();
  setRandomTween(myBitmap, "left");
  createjs.Ticker.addEventListener("tick", stage);
}
function setGeometricData(offsetX, offsetY) {
  top += offsetY;
  bottom -= offsetY;
  left += offsetX;
  right -= offsetX;
}
function setRandomTween(target, side) {
  var nextPoint = getNextPosition(side);
  var randomTime = Math.random() * 5000 + 1000;
  var easing = easings[Math.floor(Math.random() * easings.length)];
  setTween(target, nextPoint, randomTime, easing);
}
function setTween(target, myPoint, time, easing) {
  createjs.Tween.get(target)
  .to({x:myPoint.x, y:myPoint.y}, time, easing)
  .call(setRandomTween, [target, currentSide]);
}
function getNextPosition(side) {
  var nextX;
  var nextY = Math.random() * (bottom - top) + top;
  if (side == "left") {
    currentSide = "right";
    nextX = right;
  } else {
    currentSide = "left";
    nextX = left;
  }
  return new createjs.Point(nextX, nextY);
}

著者プロフィール

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

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

URLhttp://www.FumioNonaka.com/

著書

コメント

  • 変数のバッティング

    名著「AS3.0プロフェッショナルガイド」からはじまり
    いつも関連記事やHPなどで勉強させていただいています。

    さて当記事の内容について、トゥーインのステージ領域を
    きめている変数"top"ですが
    環境によってVMのグローバル変数と衝突しているため
    領域計算のためのsetGeometricData()関数内で
    "top"が数値として扱われておらず、計算結果の
    heightなどがNaNとなってしまい、その後でエラーになっている模様です。
    (ChromeDevToolsで確認しました)

    "top"⇒”myTop”で回避出来ました。

    Commented : #1  UKONN (2013/06/03, 15:39)

コメントの記入