|
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クラス」参照)。
- ImageLoader()コンストラクタに読込むファイルを引数で渡す
- 読込みの終わりはAbstractLoader.completeイベントで捉える
- ファイルはImageLoader.load()メソッドで読込む[*1]
すると、前掲サンプル001のコードは、つぎのように書替えることになりそうです。なお、抜書きの行番号は、後にまとめたコード001にもとづきます。ImageLoader()コンストラクタに読込むファイルを与えますので、ImageLoader.load()メソッドは引数をとりません。
- function initialize() {
- var canvasElement = document.getElementById("myCanvas");
- var canvasSize = new createjs.Point(canvasElement.width, canvasElement.height);
- var file = {
src: "images/image.png",
data: canvasSize
};
// var loader = new createjs.LoadQueue(false);
- var loader = new createjs.ImageLoader(file);
// loader.addEventListener("fileload", draw);
- loader.addEventListener("complete", draw);
/* loader.loadFile({
src: "images/image.png",
data: canvasSize
}); */
- loader.load();
- }
|
ところが、これだけではつぎのようなエラーが出て、コードが動きません。このエラーは、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行目)。
- function initialize() {
- var file = "images/image.png";
- var loader = new createjs.ImageLoader(file);
- loader.canvasSize = canvasSize;
- }
- function draw(eventObject) {
- var canvasSize = eventObject.target.canvasSize;
- }
|
これで、ImageLoaderクラスを使ってコードが動くようになりました。手直ししたスクリプトは、つぎのコード001にまとめてあります。併せて、jsdo.itにも改訂したサンプルのコードを掲げました(サンプル002)。
コード001■ドラッグする軌跡でアルファマスクを描く
- 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);
- var file = "images/image.png";
- stage = new createjs.Stage(canvasElement);
- var loader = new createjs.ImageLoader(file);
- loader.addEventListener("complete", draw);
- loader.canvasSize = canvasSize;
- loader.load();
- }
- function draw(eventObject) {
- var image = eventObject.result;
- var canvasSize = eventObject.target.canvasSize;
- 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.BlurFilter(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);
- }
- }
|
サンプル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.
|