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

第10回 ドラッグの軌跡を滑らかな曲線で描く

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

2次ベジエ曲線で滑らかな軌跡を描く

それでは,前回の第9回コード2に手を加えて,2次ベジエ曲線でマウスポインタの軌跡を滑らかに描いてみよう。マウスポインタの座標を納める変数(oldPoint)に加えて,中点のアンカーポイントの座標も変数(oldMidPoint)にとっておく。マウスボタンを押してドラッグを始めるリスナー関数(startWipe())は,これらふたつの変数に取りあえずマウスポインタの座標を与える。

そして,ドラッグのアニメーションのリスナー関数(wipe())は,変数(oldPoint)の座標と今現在のマウスポインタの座標の中点(midXとmidY)を求める。そして,変数のマウスポインタ座標(oldXとoldY)をコントロールポイントとして,中点座標にGraphics.quadraticCurveTo()メソッドで2次ベジエ曲線を描く。最後に,ふたつの変数のマウスポインタ座標と中点座標を新たな値に書替える。

var oldPoint = new createjs.Point();
var oldMidPoint = new createjs.Point();

function startWipe(eventObject) {
  var mousePoint = getMousePoint();
  oldMidPoint.x = oldPoint.x = mousePoint.x;
  oldMidPoint.y = oldPoint.y = mousePoint.y;

}
function wipe(eventObject) {

  var mousePoint = getMousePoint();
  var mouseX = mousePoint.x;
  var mouseY = mousePoint.y;
  var oldX = oldPoint.x;
  var oldY = oldPoint.y;
  var midX = (oldX + mouseX) / 2;
  var midY = (oldY + mouseY) / 2;
  wipingShape.graphics
  .beginStroke(createjs.Graphics.getRGB(0x0, 0.15))
  // .moveTo(oldPoint.x, oldPoint.y)
  .moveTo(oldMidPoint.x, oldMidPoint.y)
  // .lineTo(mouseX, mouseY);
  .quadraticCurveTo(oldX, oldY, midX, midY);
  oldPoint.x = mouseX;
  oldPoint.y = mouseY;
  oldMidPoint.x = midX;
  oldMidPoint.y = midY;

}

書き直したスクリプト全体は,つぎのコード1のとおりだ。これで,マウスポインタの軌跡が滑らかな曲線で描かれる図5)。これで,ひとまずお題はでき上がりだ。jsdo.itにもサンプルコードを掲げた。

コード1 ドラッグする軌跡でアルファマスクを描く

var stage;
var wipingShape;
var imageBitmap;
var blurBitmap;
var imageSize = new createjs.Point();
var radius = 10;
var bitmapPoint = new createjs.Point();
var oldPoint = new createjs.Point();
var oldMidPoint = new createjs.Point();
var isDrawing;
var cursor;
function initialize() {
  var canvasElement = document.getElementById("myCanvas");
  var canvasSize = new createjs.Point(canvasElement.width, canvasElement.height);
  stage = new createjs.Stage(canvasElement);
  var loader = new createjs.LoadQueue(false);
  loader.addEventListener("fileload", draw);
  loader.loadFile({
    src: "images/image.png", 
    data: canvasSize
    });
}
function draw(eventObject) {
  var image = eventObject.result;
  var canvasSize = eventObject.item.data;
  var imageWidth = imageSize.x = image.width;
  var imageHeight = imageSize.y = image.height;
  var nX = bitmapPoint.x = (canvasSize.x - imageWidth) / 2;
  var nY = bitmapPoint.y = (canvasSize.y - imageHeight) / 2;
  stage.addEventListener("stagemousedown", startWipe);
  stage.addEventListener("stagemouseup", stopWipe);
  stage.enableMouseOver();
  wipingShape = new createjs.Shape();
  blurBitmap = createBitmap(image, nX, nY);
  blurBitmap.filters = [new createjs.BoxBlurFilter(15, 15, 2)];
  blurBitmap.cache(0, 0, imageWidth, imageHeight);
  blurBitmap.alpha = 0.8;
  imageBitmap = createBitmap(image, nX, nY);
  createCursor();
  updateCacheImage(false);
  createjs.Ticker.addEventListener("tick", wipe);
}
function createBitmap(image, nX, nY) {
  var myBitmap = new createjs.Bitmap(image);
  myBitmap.x = nX;
  myBitmap.y = nY;
  stage.addChild(myBitmap);
  return myBitmap;
}
function createCursor() {
  cursor = new createjs.Shape();
  cursor.graphics
  .beginFill("white")
  .drawCircle(0, 0, radius);
  cursor.cursor = "pointer";
  cursor.alpha = 0.3;
  stage.addChild(cursor);
}
function startWipe(eventObject) {
  var mousePoint = getMousePoint();
  oldMidPoint.x = oldPoint.x = mousePoint.x;
  oldMidPoint.y = oldPoint.y = mousePoint.y;
  isDrawing = true;
  wipingShape.graphics
  .setStrokeStyle(radius * 2, "round", "round");
}
function wipe(eventObject) {
  cursor.x = stage.mouseX;
  cursor.y = stage.mouseY;
  if (isDrawing) {
    var mousePoint = getMousePoint();
    var mouseX = mousePoint.x;
    var mouseY = mousePoint.y;
    var oldX = oldPoint.x;
    var oldY = oldPoint.y;
    var midX = (oldX + mouseX) / 2;
    var midY = (oldY + mouseY) / 2;
    wipingShape.graphics
    .beginStroke(createjs.Graphics.getRGB(0x0, 0.15))
    .moveTo(oldMidPoint.x, oldMidPoint.y)
    .quadraticCurveTo(oldX, oldY, midX, midY);
    oldPoint.x = mouseX;
    oldPoint.y = mouseY;
    oldMidPoint.x = midX;
    oldMidPoint.y = midY;
    updateCacheImage(true);
  } else {
    stage.update();
  }
}
function stopWipe(event) {
  isDrawing = false;
}
function getMousePoint() {
  var mouseX = stage.mouseX - bitmapPoint.x;
  var mouseY = stage.mouseY - bitmapPoint.y;
  return new createjs.Point(mouseX, mouseY);
}
function updateCacheImage(update) {
  updateCache(update, wipingShape);
  var maskFilter = new createjs.AlphaMaskFilter(wipingShape.cacheCanvas);
  imageBitmap.filters = [maskFilter];
  updateCache(update, imageBitmap);
  stage.update();
}
function updateCache(update, instance) {
  if (update) {
    instance.updateCache();
  } else {
    instance.cache(0, 0, imageSize.x, imageSize.y);
  }
}

図5 マウスポインタの軌跡が滑らかな曲線でアルファマスクに描かれる

図5 マウスポインタの軌跡が滑らかな曲線でアルファマスクに描かれる

著者プロフィール

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

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

URLhttp://www.FumioNonaka.com/

著書

コメント

コメントの記入