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

第20回 立方体のワイヤーフレームを水平に回す

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

今回書上げたコード全体を以下にまとめよう。見やすさも考えて,クラス定義はscript要素を分けたコード1⁠。クラスを使い回す機会ができたら,このJavaScriptコードはJavaScript(JS)ファイルにして読み込んでもよいだろう。

コード1 EaselJS 0.7.1の読込みと3次元座標および面のクラス定義

<script src="http://code.createjs.com/easeljs-0.7.1.min.js"></script>
<script>
// Point3D
function Point3D(x, y, z) {
  this.x = x;
  this.y = y;
  this.z = z;
}
Point3D.prototype.getProjetedPoint = function(focalLength) {
  var point2D = new createjs.Point();
  var w = focalLength / (focalLength + this.z);
  point2D.x = this.x * w;
  point2D.y = this.y * w;
  return point2D;
};
// Face
function Face(pos0, pos1, pos2, pos3) {
  this.length = 4;
  this[0] = pos0;
  this[1] = pos1;
  this[2] = pos2;
  this[3] = pos3;
}
Face.prototype.getFacePoints = function (points) {
  var faces = this.length;
  var facePoints = [];
  for (var i = 0; i < faces; i++) {
    facePoints[i] = points[this[i]];
  }
  return facePoints;
};
</script>

立方体の4面をワイヤーフレームで描き,マウスポインタの位置に応じて水平に回すアニメーションのスクリプトは以下のとおりだコード2⁠。つぎは,立方体の4面を塗りたい。その場合,前回第19回3次元空間で弾むオブジェクトとz座標による重ね順の並べ替えで学んだように,面の重ね順を考えなければならない。次回は,配列の並べ替えではなく,ベクトルの外積を使って解決する。

コード2 ワイヤーフレームで描いた立方体の4面をマウスポインタの位置に応じて水平に回す

<script>
var stage;
var drawGraphics;
var points;
var angle = 0;
var matrix = new createjs.Matrix2D();
var stageCenterX;
var _point = new createjs.Point();
var points2D = [];
var facesVertices;
var focalLength = 300;
function initialize() {
  var canvasElement = document.getElementById("myCanvas");
  stage = new createjs.Stage(canvasElement);
  stageCenterX = canvasElement.width / 2;
  drawGraphics = createGraphics(stageCenterX, canvasElement.height / 2);
  points = createCubePoints(50);
  facesVertices = getFacesVertices();
  drawFaces(points, facesVertices);
  createjs.Ticker.addEventListener("tick", rotate);
  stage.addEventListener("stagemousemove", setAngle);
}
function setAngle(eventObject) {
  var mouseX = eventObject.stageX;
  angle = (mouseX - stageCenterX) * 1 / 300;
}
function rotate(eventObject) {
  var count = points.length;
  points2D.length = 0;
  matrix.identity().rotate(angle);
  for (var i = 0; i < count; i++) {
    var point = points[i];
    matrix.transformPoint(point.x, point.z, _point);
    point.x = _point.x;
    point.z = _point.y;
    points2D[i] = point.getProjetedPoint(focalLength);
  }
  drawFaces(points2D, facesVertices);
}
function drawFaces(points, faces) {
  var numFaces = faces.length;
  drawGraphics.clear();
  for (var i = 0; i < numFaces; i++) {
    var face = faces[i];
    var facePoints = face.getFacePoints(points);
    draw(facePoints);
  }
  stage.update();
}
function draw(points) {
  var count = points.length;
  var point = points[count - 1];
  drawGraphics
  .beginStroke("mediumblue")
  .setStrokeStyle(1)
  .moveTo(point.x, point.y);
  for (var i = 0; i < count; i++) {
    point = points[i];
    drawGraphics.lineTo(point.x, point.y);
  }
}
function createGraphics(x, y) {
  var drawShape = new createjs.Shape();
  drawShape.x = x;
  drawShape.y = y;
  stage.addChild(drawShape);
  return drawShape.graphics;
}
function createCubePoints(halfEdge) {
  var cubePoints = [
    new Point3D(-halfEdge, -halfEdge, -halfEdge),
    new Point3D(halfEdge,  -halfEdge, -halfEdge),
    new Point3D(halfEdge, halfEdge, -halfEdge),
    new Point3D(-halfEdge, halfEdge, -halfEdge),
    new Point3D(-halfEdge, -halfEdge, halfEdge),
    new Point3D(halfEdge, -halfEdge, halfEdge),
    new Point3D(halfEdge, halfEdge, halfEdge),
    new Point3D(-halfEdge, halfEdge, halfEdge)
  ];
  return cubePoints;
}
function getFacesVertices() {
  var vertices = [
    new Face(0, 1, 2, 3),
    new Face(1, 5, 6, 2),
    new Face(4, 0, 3, 7),
    new Face(5, 4, 7, 6)
  ];
  return vertices;
}
</script>

いつものとおり,jsdo.itにもサンプルを掲げた。クラス定義のscript要素は[HTML]の欄に加えてある。

著者プロフィール

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

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

URLhttp://www.FumioNonaka.com/

著書