株式会社ライブキャストロゴ 株式会社ライブキャスト

flashcast:フリーで働くITエンジニア集団のブログ: Macで動くAIRアプリのDockアイコンをカスタマイズする方法の続きです。

Macで起動するAIRアプリのドックアイコンをアニメーションさせたいと思います。使用した画像はこちら。Flex SDK3.2に同梱されているものを加工しました。
AIRApp_icon128.png



ソースはこちら。

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="horizontal" creationComplete="onInit()">
<mx:Script>
<![CDATA[
import mx.core.BitmapAsset;
[Embed(source="assets/AIRApp_icon128.png")]
private var icon128:Class;

[Embed(source="assets/AIRApp_icon16.png")]
private var icon16:Class;

private var newIconBitmap:BitmapData;
private var isAnimation:Boolean = false;

private function onInit():void {
 if (NativeApplication.supportsDockIcon) {
  var bitmap128:BitmapData =
   (new icon128() as BitmapAsset).bitmapData;
  var dockIcon:DockIcon =
   NativeApplication.nativeApplication.icon as DockIcon;
  dockIcon.bitmaps = [bitmap128];
 }
 else if (NativeApplication.supportsSystemTrayIcon) {
  var bitmap16:BitmapData =
   (new icon16() as BitmapAsset).bitmapData;
  var trayIcon:SystemTrayIcon =
   NativeApplication.nativeApplication.icon as SystemTrayIcon;
  trayIcon.bitmaps = [bitmap16];
 }
}

private function onClick(event:MouseEvent):void {
 if (isAnimation) {
  this.removeEventListener(Event.ENTER_FRAME, onAnimation);
  btnAnimation.label = "Animation";
 }
 else {
  if (NativeApplication.supportsDockIcon) {
   newIconBitmap = (new icon128() as BitmapAsset).bitmapData;
  }
  else if (NativeApplication.supportsSystemTrayIcon) {
   newIconBitmap = (new icon16() as BitmapAsset).bitmapData;
  }
  this.addEventListener(Event.ENTER_FRAME, onAnimation);
  btnAnimation.label = "Stop";
 }

 isAnimation = !isAnimation;
}

private function onAnimation(event:Event):void {
 var iconBitmap:BitmapData;
 var matrix:Matrix;
 var rectangle:Rectangle;

 if (NativeApplication.supportsDockIcon) {
  var dockIcon:DockIcon =
   NativeApplication.nativeApplication.icon as DockIcon;
  iconBitmap = new BitmapData(128, 128, true, 0x00000000);
  matrix = new Matrix(1, 0, 0, 1, 0, -1);
  rectangle = new Rectangle(0, 0, 128, 128);

  iconBitmap.draw(newIconBitmap, matrix, null, null, rectangle);
  matrix = new Matrix(1, 0, 0, 1, 0, 127);
  iconBitmap.draw(newIconBitmap, matrix, null, null, rectangle);
  newIconBitmap = iconBitmap.clone();

  dockIcon.bitmaps = [newIconBitmap];
 }
 else if (NativeApplication.supportsSystemTrayIcon) {
  var trayIcon:SystemTrayIcon =
   NativeApplication.nativeApplication.icon as SystemTrayIcon;
  iconBitmap = new BitmapData(16, 16, true, 0x00000000);
  matrix = new Matrix(1, 0, 0, 1, 0, -1);
  rectangle = new Rectangle(0, 0, 16, 16);

  iconBitmap.draw(newIconBitmap, matrix, null, null, rectangle);
  matrix = new Matrix(1, 0, 0, 1, 0, 15);
  iconBitmap.draw(newIconBitmap, matrix, null, null, rectangle);
  newIconBitmap = iconBitmap.clone();

  trayIcon.bitmaps = [newIconBitmap];
 }
}
]]>
</mx:Script>
<mx:Button label="Animation" id="btnAnimation" click="onClick(event)"/>
</mx:WindowedApplication>

このアプリを起動するとDockにアイコンが表示されると同時に、以下の画面が開きます。

[Animation]ボタンをクリックすると、Dockアイコンが縦にくるくる動き始めます。まず最初のポイントです。[Animation]ボタンのクリックイベントでDockアイコンがアニメーションしているかどうかを判定して、アニメーションしていなければEvent.ENTER_FRAMEのイベントハンドラ(リスナー)を登録しています。46行目です。

this.addEventListener(Event.ENTER_FRAME, onAnimation);

アニメーションしていた場合は、Event.ENTER_FRAMEのイベントハンドラ(リスナー)を削除してアニメーションをストップします。36行目です。

this.removeEventListener(Event.ENTER_FRAME, onAnimation);

Flashに詳しい人ならわかると思うのですが、Event.ENTER_FRAMEとはムービークリップがステージに存在している間、フレームが更新されるたびに発生するイベントです。

[ブロードキャストイベント] 再生ヘッドが新しいフレームに入るときに送出されます。再生ヘッドが移動しない場合、またはフレームが 1 つしか存在しない場合、このイベントはフレームレートに合わせて継続的に送出されます。 このイベントはブロードキャストイベントであるため、このイベントに登録されているリスナーを持つすべての表示イベントによって送出されます。

DisplayObject – ActionScript 3.0 言語およびコンポーネントリファレンスより引用。

要するにAIRアプリの場合は起動中ずっと裏で発生していることになります。このイベントハンドラ(onAnimation)で何をしているかといいますと、まず61行目で、128pxで無色透明(ARGBの0x00000000)の正方形のBitmapオブジェクトを生成します。

iconBitmap = new BitmapData(128, 128, true, 0x00000000);

次に、AIRApp_icon128.pngの画像を格納したBitmapをMatrixクラスで操作していきます。Matrixクラスとは何かと言うと、Bitmap等のオブジェクトを平行移動、拡大 / 縮小、回転、傾斜したりすることが出来るクラスです。詳細はこちらをどうぞ。
Matrix – ActionScript 3.0 言語およびコンポーネントリファレンス
62行目になります。

matrix = new Matrix(1, 0, 0, 1, 0, -1);

では、AIRApp_icon128.pngを1pxずつ上に平行移動するためのMatrixオブジェクトを生成しています。

65行目では、128pxで無色透明の正方形のBitmap(iconBitmap)の上に、(newIconBitmapとmatrixで)1px上に平行移動させたBitmapを上書いています。

iconBitmap.draw(newIconBitmap, matrix, null, null, rectangle);

これを繰り返すと、こんな感じになります。
[上にフェードアウトしていく感じの画像]

同じように

matrix = new Matrix(1, 0, 0, 1, 0, 127);
iconBitmap.draw(newIconBitmap, matrix, null, null, rectangle);

66行目で、まずAIRApp_icon128.pngを127pxずつ下に平行移動するためのMatrixオブジェクトを生成しています。67行目では、65行目でdrawしたBitmapに更に、127px下に平行移動させたBitmapを上書いています。上書いているのは、上で1px平行移動させて枠からはみでたように見える部分です。

[下から昇ってくる感じの画像]

[上にフェードアウトしていく感じの画像]と[下から昇ってくる感じの画像]をガッチャンコさせてる感じですね。ガッチャンコを動かすと、、、

ちなみに、Windowsのタスクトレイアイコンの場合は、こんな感じです。

あたかもアニメーションしているように見えるんですねぇ~、これが。ソースコードは同じものを使用しています。ただ、どちらも1pxずつ移動させているのでDockアイコンのアニメーションはすごーく遅いです。が、フレームレートや移動量で調整可能です。これで一応、アニメーションも出来ました!

■関連記事へのリンク
flashcast:フリーで働くITエンジニア集団のブログ: Macで動くAIRアプリのDockアイコンをカスタマイズする方法(2009/2/3追記)
flashcast:フリーで働くITエンジニア集団のブログ: Macで動くAIRアプリのカスタマイズしたDockアイコンを回転させる方法 〜概要編〜(2009/2/3追記)
flashcast:フリーで働くITエンジニア集団のブログ: Macで動くAIRアプリのカスタマイズしたDockアイコンを回転させる方法 〜実装編〜(2009/2/3追記)
flashcast:フリーで働くITエンジニア集団のブログ: Macで動くAIRアプリのカスタマイズしたDockアイコンを縮小/拡大させる方法(2009/2/4追記)