サイトトップ

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

HTML5テクニカルノート

EaselJSでインスタンスにマスクをかける

ID: FN1209005 Technique: HTML5 and JavaScript

2012年8月にCreateJS Suiteの新しいバージョンが公開されました。そして、新たなEaselJS 0.5.0にはDisplayObject.maskプロパティが備わり、インスタンスをShapeオブジェクトでマスクできるようになりました。本稿ではこのプロパティを試します。


01 ふたつ重ねた同じ画像のインスタンスの下側にフィルタをかける

まずは、同じ画像が読込まれたBitmapインスタンスをふたつ重ね、その下側のインスタンスにフィルタをかけます。そして、次項で手前のインスタンスをマスクで抜くつもりです。

使うフィルタはふたつです。第1に、ColorMatrixFilterで画像イメージをセピア調に変えます。DisplayObjectインスタンスへのフィルタのかけ方とColorMatrixFilterの操作については、「EaselJSのフィルタColorMatrixFilterでイメージをセピア調に変える」をお読みください。

第2に、BoxBlurFilterで矩形領域にぼかしをかけます。コンストラクタには3つの引数を渡して、ぼかし方が決められます。初めのふたつの引数はぼかし幅で、ピクセルを単位とします。最後の引数はぼかしの品質とされ、処理する回数を1から3までの整数で定めます。

new BoxBlurFilter(ぼかす水平ピクセル数, ぼかす垂直ピクセル数, ぼかし品質)

以下のコード001は、同じ画像が読込まれたBitmapインスタンスをふたつ重ねて、その下側インスタンスにぼかしとセピア調カーラーのフィルタをかけます。基本的な処理の組立ては、前出「EaselJSのフィルタColorMatrixFilterでイメージをセピア調に変える」のコード002と同じです。ただ、Bitmapインスタンスの数がふたつに増えています。そのふたつのインスタンスのBitmap.imageプロパティには、同じ画像イメージ(Imageオブジェクト)が定められていることに注目しておきましょう(第50〜51および第57行目)。

コード001■ふたつ重ねた同じ画像が読込まれたBitmapインスタンスの下側にフィルタをかける
  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="easeljs/utils/UID.js"></script>
  5. <script src="easeljs/geom/Matrix2D.js"></script>
  6. <script src="easeljs/geom/Point.js"></script>
  7. <script src="easeljs/events/MouseEvent.js"></script>
  8. <script src="easeljs/display/DisplayObject.js"></script>
  9. <script src="easeljs/display/Container.js"></script>
  10. <script src="easeljs/display/Stage.js"></script>
  11. <script src="easeljs/display/Bitmap.js"></script>
  12. <script src="easeljs/filters/Filter.js"></script>
  13. <script src="easeljs/filters/BoxBlurFilter.js"></script>
  14. <script src="easeljs/filters/ColorMatrixFilter.js"></script>
  15. <script src="easeljs/filters/ColorMatrix.js"></script>
  16. <script src="preloadjs/AbstractLoader.js"></script>
  17. <script src="preloadjs/PreloadJS.js"></script>
  18. <script src="preloadjs/TagLoader.js"></script>
  19. <script src="preloadjs/XHRLoader.js"></script>
  20. <script>
  21. var stage;
  22. var file = "images/Pen.png";
  23. var filtersList = [];
  24. function initialize() {
  25.   var canvasElement = document.getElementById("myCanvas");
  26.   stage = new Stage(canvasElement);
  27.   var colorSepia = [
  28.     0.393, 0.769, 0.189, 0, 0,
  29.     0.349, 0.686, 0.168, 0, 0,
  30.     0.272, 0.534, 0.131, 0, 0,
  31.     0, 0, 0, 1, 0
  32.     ];
  33.   var loader = new PreloadJS(false);
  34.   loader.onFileLoad = draw;
  35.   loader.center = new Point(canvasElement.width / 2, canvasElement.height / 2);
  36.   loader.loadFile({src:file});
  37.   filtersList.push(new BoxBlurFilter(2, 2, 2));
  38.   filtersList.push(new ColorMatrixFilter(colorSepia));
  39. }
  40. function setAppearance(instance, nX, nY) {
  41.   instance.x = nX;
  42.   instance.y = nY;
  43.   stage.addChild(instance);
  44. }
  45. function draw(eventObject) {
  46.   var myImage = eventObject.result;
  47.   var center = this.center;
  48.   var centerX = center.x;
  49.   var centerY = center.y;
  50.   setFilter(createBitmap(centerX, centerY, myImage));
  51.   createBitmap(centerX + 20, centerY, myImage);
  52.   stage.update();
  53. }
  54. function createBitmap(nX, nY, myImage) {
  55.   var myBitmap = new Bitmap();
  56.   setAppearance(myBitmap, nX - myImage.width / 2, nY - myImage.height / 2);
  57.   myBitmap.image = myImage;
  58.   return myBitmap;
  59. }
  60. function setFilter(myBitmap) {
  61.   var myImage = myBitmap.image;
  62.   myBitmap.filters = filtersList;
  63.   myBitmap.cache(0, 0, myImage.width, myImage.height);
  64. }
  65. </script>

前掲コード001では、下のBitmapインスタンスにフィルタがかかったことを確かめられるように、上のインスタンスは水平位置を少しずらしました(図001)。次項で上のインスタンスをマスクで抜くときには、位置は揃えます。

図001■ふたつ重ねた同じ画像のBitmapインスタンスの下にフィルタがかかった
図001


02 Shapeオブジェクトのマスクでインスタンスを抜く

それでは、前掲コード001に手を加えて、手前のBitmapインスタンスをマスクで抜きます。マスクをかけるには、DisplayObject.maskプロパティに、マスクのかたちで描いたShapeオブジェクトを定めます。

DisplayObjectオブジェクト.mask = Shapeオブジェクト

Shapeオブジェクトに描画しますので、script要素にはShapeとGraphicsのふたつのクラスを読込んでおきます(第12〜13行目)。なお、行番号は後にscript要素全体を掲げるコード002にもとづきます。

  1. <script src="easeljs/display/Shape.js"></script>
  2. <script src="easeljs/display/Graphics.js"></script>

マスクにするShapeインスタンスは、後で使い回しやすいように変数(myShape)で宣言しておきます(第27行目)。そして、マスクのShapeインスタンスをつくる関数(createShape())は別に定め、AbstractLoader.onFileLoadイベントのハンドラ(draw())から呼出します(第54行目)。関数でつくるShapeは星形にしました(「EaselJSで描いた星形を回す」01「EaselJSで星形を描く」参照)。

このマスクのShapeインスタンスをつくる関数(createShape())の中で、Container.addChild()メソッドが使われていないことにご注目ください。マスクにするインスタンスを見せなくてよい場合には、Stageオブジェクトの表示リストに加えなくてもよいのです。マスクを設定する関数(setMask())は別に定めて、ロードのイベントハンドラ(draw())から呼出しました(第56行目)。

  1. var myShape;
  1. function draw(eventObject) {
  1.   myShape = createShape(centerX, centerY, 80);
  1.   setMask(createBitmap(centerX, centerY, myImage), myShape);
  1. }
  1. function createShape(nX, nY, radius) {
  2.   var myShape = new Shape();
  3.   var myGraphics = myShape.graphics;
  4.   myGraphics.drawPolyStar(0, 0, radius, 5, 0.6, -90);
  5.   myShape.x = nX;
  6.   myShape.y = nY;
  7.   return myShape;
  8. }
  9. function setMask(instance, myShape) {
  10.   instance.mask = myShape;
  11. }

同じ画像のBitmapインスタンスをふたつ重ね、下にはフィルタをかけ、上のインスタンスは星形のマスクで抜いたのが、以下のコード002です。もっとも、それだけではつまらないので、Tickerクラスを用いて(第14および第57行目)、tickイベントのアニメーションでマスクを回しました(第82〜85行目)。Tickerクラスを使ったアニメーションについては、前出「EaselJSで描いた星形を回す」02「EaselJSを使ったスクリプトによるアニメーション」をお読みください。

コード002■ふたつ重ねたBitmapインスタンスの手前側にかけた星形のマスクを回す
  1. <script>
  2. var createjs = window;
  3. </script>
  4. <script src="easeljs/utils/UID.js"></script>
  5. <script src="easeljs/geom/Matrix2D.js"></script>
  6. <script src="easeljs/geom/Point.js"></script>
  7. <script src="easeljs/events/MouseEvent.js"></script>
  8. <script src="easeljs/display/DisplayObject.js"></script>
  9. <script src="easeljs/display/Container.js"></script>
  10. <script src="easeljs/display/Stage.js"></script>
  11. <script src="easeljs/display/Bitmap.js"></script>
  12. <script src="easeljs/display/Shape.js"></script>
  13. <script src="easeljs/display/Graphics.js"></script>
  14. <script src="easeljs/utils/Ticker.js"></script>
  15. <script src="easeljs/filters/Filter.js"></script>
  16. <script src="easeljs/filters/BoxBlurFilter.js"></script>
  17. <script src="easeljs/filters/ColorMatrixFilter.js"></script>
  18. <script src="easeljs/filters/ColorMatrix.js"></script>
  19. <script src="preloadjs/AbstractLoader.js"></script>
  20. <script src="preloadjs/PreloadJS.js"></script>
  21. <script src="preloadjs/TagLoader.js"></script>
  22. <script src="preloadjs/XHRLoader.js"></script>
  23. <script>
  24. var stage;
  25. var file = "images/Pen.png";
  26. var filtersList = [];
  27. var myShape;
  28. function initialize() {
  29.   var canvasElement = document.getElementById("myCanvas");
  30.   stage = new Stage(canvasElement);
  31.   var colorSepia = [
  32.     0.393, 0.769, 0.189, 0, 0,
  33.     0.349, 0.686, 0.168, 0, 0,
  34.     0.272, 0.534, 0.131, 0, 0,
  35.     0, 0, 0, 1, 0
  36.     ];
  37.   var loader = new PreloadJS(false);
  38.   loader.onFileLoad = draw;
  39.   loader.center = new Point(canvasElement.width / 2, canvasElement.height / 2);
  40.   loader.loadFile({src:file});
  41.   filtersList.push(new BoxBlurFilter(2, 2, 2));
  42.   filtersList.push(new ColorMatrixFilter(colorSepia));
  43. }
  44. function setAppearance(instance, nX, nY) {
  45.   instance.x = nX;
  46.   instance.y = nY;
  47.   stage.addChild(instance);
  48. }
  49. function draw(eventObject) {
  50.   var myImage = eventObject.result;
  51.   var center = this.center;
  52.   var centerX = center.x;
  53.   var centerY = center.y;
  54.   myShape = createShape(centerX, centerY, 80);
  55.   setFilter(createBitmap(centerX, centerY, myImage));
  56.   setMask(createBitmap(centerX, centerY, myImage), myShape);
  57.   Ticker.addListener(window);
  58.   stage.update();
  59. }
  60. function createBitmap(nX, nY, myImage) {
  61.   var myBitmap = new Bitmap();
  62.   setAppearance(myBitmap, nX - myImage.width / 2, nY - myImage.height / 2);
  63.   myBitmap.image = myImage;
  64.   return myBitmap;
  65. }
  66. function setFilter(myBitmap) {
  67.   var myImage = myBitmap.image;
  68.   myBitmap.filters = filtersList;
  69.   myBitmap.cache(0, 0, myImage.width, myImage.height);
  70. }
  71. function createShape(nX, nY, radius) {
  72.   var myShape = new Shape();
  73.   var myGraphics = myShape.graphics;
  74.   myGraphics.drawPolyStar(0, 0, radius, 5, 0.6, -90);
  75.   myShape.x = nX;
  76.   myShape.y = nY;
  77.   return myShape;
  78. }
  79. function setMask(instance, myShape) {
  80.   instance.mask = myShape;
  81. }
  82. function tick() {
  83.   myShape.rotation += 5;
  84.   stage.update();
  85. }
  86. </script>

これで、フィルタのかかった画像の上で、もと画像を抜いた星形のマスクが回るアニメーションになります(図002)。

図002■フィルタのかかった画像の上でもと画像を抜いたマスクが回る
図002左   図002右


作成者: 野中文雄
作成日: 2012年9月10日


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