サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

PreloadJS 0.6.0: 古いコードのイメージ読込みをImageLoaderクラスで書直す

ID: FN1501006 Technique: HTML5 and JavaScript Library: EaselJS 0.8.0 and PreloadJS 0.6.0

PreloadJS 0.6.0から、コンテンツの形式に応じたローダをクラスとして備えました。イメージファイルはImageLoaderクラスで読込みます。LoadQueueクラスは、コンテンツの形式が何か調べてローダーを選びます。けれど、読込むのが初めからイメージとわかっているときは、ImageLoaderクラスを使った方がひと手間省けるのです。本稿では、古いバージョンで書いたコードを、ImageLoaderクラスで書替えてみます。


01 お題「ドラッグする軌跡でアルファマスクを描く」

コード書替えのお題は、gihyo.jp連載「HTML5のCanvasでつくるダイナミックな表現―CreateJSを使う」 第10回「ドラッグの軌跡を滑らかな曲線で描く」コード1「ドラッグする軌跡でアルファマスクを描く」です(サンプル001)。読込んだ画像イメージをフィルタでぼかし、ドラッグでアルファマスクを描いています。使ったライブラリは、EaselJS 0.6.1とPreloadJS 0.3.1です。

サンプル001■Wiping out blur from a image with AlphaMaskFilter New

EaselJS 0.6.1はライブラリのデータサイズを気づかって、フィルタのクラスが含まれておらず、別に読込んでいました。けれど、使いにくい・わかりにくいという声から、つぎの0.7.0でフィルタも含まれるようになりました。また、同バージョンで、ぼかしフィルタのクラス名がBoxBlurFilterからBlurFilterに変わりました。前掲サンプル001は、つぎのようにこのクラス名さえ改めれば正しく動きます。

function draw(eventObject) {

  blurBitmap = createBitmap(image, nX, nY);
  // blurBitmap.filters = [new createjs.BoxBlurFilter(15, 15, 2)];
  blurBitmap.filters = [new createjs.BlurFilter(15, 15, 2)];
  blurBitmap.cache(0, 0, imageWidth, imageHeight);

}


02 LoadQueueをImageLoaderクラスに差替える

ImageLoaderクラスは、イメージファイルをつぎのような手順で読込みます。なお、ImageLoader()コンストラクタに渡す引数は、読込むファイルを示すオブジェクトまたはパスの文字列です(詳しくは「ImageLoaderクラス」参照)。

  1. ImageLoader()コンストラクタに読込むファイルを引数で渡す
  2. 読込みの終わりはAbstractLoader.completeイベントで捉える
  3. ファイルはImageLoader.load()メソッドで読込む[*1]

すると、前掲サンプル001のコードは、つぎのように書替えることになりそうです。なお、抜書きの行番号は、後にまとめたコード001にもとづきます。ImageLoader()コンストラクタに読込むファイルを与えますので、ImageLoader.load()メソッドは引数をとりません。

  1. function initialize() {
  2.   var canvasElement = document.getElementById("myCanvas");
  3.   var canvasSize = new createjs.Point(canvasElement.width, canvasElement.height);
  4.   var file = {
        src: "images/image.png",
        data: canvasSize
      };
      // var loader = new createjs.LoadQueue(false);
  1.   var loader = new createjs.ImageLoader(file);
      // loader.addEventListener("fileload", draw);
  2.   loader.addEventListener("complete", draw);
      /* loader.loadFile({
        src: "images/image.png",
        data: canvasSize
        }); */
  1.   loader.load();
  2. }

ところが、これだけではつぎのようなエラーが出て、コードが動きません。このエラーは、AbstractLoader.completeイベントのリスナー関数の受取ったイベントオブジェクト(eventObject)が、itemというプロパティをもっていないことから起こりました。

TypeError: undefined is not an object (evaluating 'eventObject.item.data')

[*1] 「PreloadJS v0.6.0 API Documentation」で「ImageLoader Class」の「load()」の項を見ると、 AbstractLoader.load()メソッドを継承すると書かれています。けれど、ImageLoaderクラスの実装では、メソッドがオーバーライドされています。


03 AbstractLoader.completeイベントのリスナー関数にデータを渡す

LoadQueue.loadFile()メソッドを用いると、引数のオブジェクトのdataというプロパティに定めた値が、LoadQueue.fileloadイベントのリスナー関数に渡されるイベントオブジェクトのitemプロパティに加えられます。前掲サンプル001は、つぎのようにしてリスナー関数(draw())にdataプロパティを受け渡していました。ところが、ImageLoaderクラスにはloadFile()メソッドが備わっておらず、AbstractLoader.completeイベントのリスナー関数が受取るイベントオブジェクトにitemというプロパティはないのです。

function initialize() {

  var loader = new createjs.LoadQueue(false);
  loader.addEventListener("fileload", draw);
  loader.loadFile({
    src: "images/image.png",
    data: canvasSize
    });
}
function draw(eventObject) {

  var canvasSize = eventObject.item.data;

}

リスナー関数(draw())にdataプロパティでデータを渡すことは、あきらめるより仕方ありません。そのかわり、ローダーのImageLoaderオブジェクト(loader)に、プロパティ(canvasSize)としてデータを与えることにしました(第19行目)。リスナー関数は受取ったイベントオブジェクト(eventObject)のEvent.targetプロパティから、読込んだローダーの参照が得られます(第24行目)。なお、dataプロパティが使えませんので、ImageLoader()コンストラクタに渡す引数(file)は、パスの文字列としました(第15行目)。

  1. function initialize() {
  1.   var file = "images/image.png";
  1.   var loader = new createjs.ImageLoader(file);
  1.   loader.canvasSize = canvasSize;
  1. }
  2. function draw(eventObject) {
  1.   var canvasSize = eventObject.target.canvasSize;
  1. }

これで、ImageLoaderクラスを使ってコードが動くようになりました。手直ししたスクリプトは、つぎのコード001にまとめてあります。併せて、jsdo.itにも改訂したサンプルのコードを掲げました(サンプル002)。

コード001■ドラッグする軌跡でアルファマスクを描く
  1. var stage;
  2. var wipingShape;
  3. var imageBitmap;
  4. var blurBitmap;
  5. var imageSize = new createjs.Point();
  6. var radius = 10;
  7. var bitmapPoint = new createjs.Point();
  8. var oldPoint = new createjs.Point();
  9. var oldMidPoint = new createjs.Point();
  10. var isDrawing;
  11. var cursor;
  12. function initialize() {
  13.   var canvasElement = document.getElementById("myCanvas");
  14.   var canvasSize = new createjs.Point(canvasElement.width, canvasElement.height);
  15.   var file = "images/image.png";
  16.   stage = new createjs.Stage(canvasElement);
  17.   var loader = new createjs.ImageLoader(file);
  18.   loader.addEventListener("complete", draw);
  19.   loader.canvasSize = canvasSize;
  20.   loader.load();
  21. }
  22. function draw(eventObject) {
  23.   var image = eventObject.result;
  24.   var canvasSize = eventObject.target.canvasSize;
  25.   var imageWidth = imageSize.x = image.width;
  26.   var imageHeight = imageSize.y = image.height;
  27.   var nX = bitmapPoint.x = (canvasSize.x - imageWidth) / 2;
  28.   var nY = bitmapPoint.y = (canvasSize.y - imageHeight) / 2;
  29.   stage.addEventListener("stagemousedown", startWipe);
  30.   stage.addEventListener("stagemouseup", stopWipe);
  31.   stage.enableMouseOver();
  32.   wipingShape = new createjs.Shape();
  33.   blurBitmap = createBitmap(image, nX, nY);
  34.   blurBitmap.filters = [new createjs.BlurFilter(15, 15, 2)];
  35.   blurBitmap.cache(0, 0, imageWidth, imageHeight);
  36.   blurBitmap.alpha = 0.8;
  37.   imageBitmap = createBitmap(image, nX, nY);
  38.   createCursor();
  39.   updateCacheImage(false);
  40.   createjs.Ticker.addEventListener("tick", wipe);
  41. }
  42. function createBitmap(image, nX, nY) {
  43.   var myBitmap = new createjs.Bitmap(image);
  44.   myBitmap.x = nX;
  45.   myBitmap.y = nY;
  46.   stage.addChild(myBitmap);
  47.   return myBitmap;
  48. }
  49. function createCursor() {
  50.   cursor = new createjs.Shape();
  51.   cursor.graphics
  52.   .beginFill("white")
  53.   .drawCircle(0, 0, radius);
  54.   cursor.cursor = "pointer";
  55.   cursor.alpha = 0.3;
  56.   stage.addChild(cursor);
  57. }
  58. function startWipe(eventObject) {
  59.   var mousePoint = getMousePoint();
  60.   oldMidPoint.x = oldPoint.x = mousePoint.x;
  61.   oldMidPoint.y = oldPoint.y = mousePoint.y;
  62.   isDrawing = true;
  63.   wipingShape.graphics
  64.   .setStrokeStyle(radius * 2, "round", "round");
  65. }
  66. function wipe(eventObject) {
  67.   cursor.x = stage.mouseX;
  68.   cursor.y = stage.mouseY;
  69.   if (isDrawing) {
  70.     var mousePoint = getMousePoint();
  71.     var mouseX = mousePoint.x;
  72.     var mouseY = mousePoint.y;
  73.     var oldX = oldPoint.x;
  74.     var oldY = oldPoint.y;
  75.     var midX = (oldX + mouseX) / 2;
  76.     var midY = (oldY + mouseY) / 2;
  77.     wipingShape.graphics
  78.     .beginStroke(createjs.Graphics.getRGB(0x0, 0.15))
  79.     .moveTo(oldMidPoint.x, oldMidPoint.y)
  80.     .quadraticCurveTo(oldX, oldY, midX, midY);
  81.     oldPoint.x = mouseX;
  82.     oldPoint.y = mouseY;
  83.     oldMidPoint.x = midX;
  84.     oldMidPoint.y = midY;
  85.     updateCacheImage(true);
  86.   } else {
  87.     stage.update();
  88.   }
  89. }
  90. function stopWipe(event) {
  91.   isDrawing = false;
  92. }
  93. function getMousePoint() {
  94.   var mouseX = stage.mouseX - bitmapPoint.x;
  95.   var mouseY = stage.mouseY - bitmapPoint.y;
  96.   return new createjs.Point(mouseX, mouseY);
  97. }
  98. function updateCacheImage(update) {
  99.   updateCache(update, wipingShape);
  100.   var maskFilter = new createjs.AlphaMaskFilter(wipingShape.cacheCanvas);
  101.   imageBitmap.filters = [maskFilter];
  102.   updateCache(update, imageBitmap);
  103.   stage.update();
  104. }
  105. function updateCache(update, instance) {
  106.   if (update) {
  107.     instance.updateCache();
  108.   } else {
  109.     instance.cache(0, 0, imageSize.x, imageSize.y);
  110.   }
  111. }

サンプル002■EaselJS 0.8.0 & PreloadJS 0.6.0: Wiping out blur from a image with AlphaMaskFilter



作成者: 野中文雄
作成日: 2015年1月26日


Copyright © 2001-2015 Fumio Nonaka.  All rights reserved.