‘Flash’ カテゴリーのリスト

Flashのレイヤーマスクをスクリプト制御する場合の挙動[AS3]

2011 年 9 月 5 日 月曜日

Flashのタイムラインパネルで設定するマスクの挙動が「ん?」って感じだったので色々検証してみました。
具体的には、パネル上で適用したマスクをスクリプトで制御する場合。

いろいろ検証してみました

手前にマスク用のムービークリップ[masker](グレー)と、その下にマスクを適用するムービークリップ[mc](イエロー)を配置。

マスク適用前

マスク適用前

レイヤーマスクを適用。
masker(グレー)にmc(イエロー)がマスクされて表示される。
タイムラインパネル

タイムラインパネル

マスク適用後

マスク適用後


通常だとこの状態は下記のスクリプトと同じ状態になる。

// mcのマスクとしてmaskerを適用
mc.mask = masker;
このマスクをスクリプトで解除しようとしてみたところ、うまくいかない。

// mcのマスクを解除
mc.mask = null;

スクリプトでマスクを解除

マスクが解除されない


マスクが解除されない。
試しにmcのマスクを出力してみると

// mcのマスクを出力してみる
trace(mc.mask) // 出力 null

となる。

visibleをfalseにしても解除されない。
maskerをremoveChildするとmcのマスクが解除される。

// maskerを表示リストから削除
removeChild(masker);

removeChildした後

マスクが解除された

じゃあremoveChildしたmaskerをaddChildすればマスクは復活するかと思いきや、addChildしただけではmaskerは何も表示されなくなってしまう。

// maskerを再配置
addChild(masker);

addChildした後

マスクは適用されない

なので、removeChildしたmaskerを使い回したい場合は、addChildした後にスクリプトでmaskを適用してやる必要がある。

// removeChildしたmaskerをもう一度
// マスクとして適用
removeChild(masker);

// もう一度マスクをセット
// これで正常に表示される
addChild(masker);
mc.mask = masker;

addChildした後にマスクを設定

正常にマスクが適用された

もしくは、addChildではなくてaddChildAtで、mcよりも下に配置してやると正常にmaskが復活する。
この場合はマスクを再設定する必要はない。

// removeChildしたmaskerをもう一度
// マスクとして適用
removeChild(masker);

// mcよりも下に配置
addChildAt(masker,0);

addChildAtで深度を指定

これでも正常に適用される

ここからがさらに不思議なところで、レイヤーマスクを適用している状態で試しにmaskerのmaskを出力してみると当然のことながらnullが返ってくる。

// maskerのマスクを出力
trace(masker.mask) // 出力 null

ところが、maskerのマスクを解除するスクリプトを書くと、なぜかmcのマスクが解除される。
しかも、mcの上に配置されているはずのmaskerはmcの下に深度が変更される。

// maskerのマスクを解除
masker.mask = null;

マスクオブジェクトのmaskを解除

マスクが解除された

さらに掘り下げてみた。レイヤーマスクは適用せず、スクリプトでマスクを設定。その状態でmc、maskerのmaskを出力してみると、お互いをmaskとして出力する。

// お互いのマスクを出力してみる
mc.mask = masker;

trace(mc.mask.name); // 出力 masker
trace(masker.mask.name); // 出力 mc

最後に、マスクされている状態でそれぞれの深度を出力してみると、マスクオブジェクトの深度が変更されている。

// マスクを適用
mc.mask = masker;

// 深度を出力
trace(getChildIndex(mc)); // 出力 1
trace(getChildIndex(masker)); // 出力 0

結論

検証の結果からわかったこと。

  1. レイヤーマスクはremoveChildするとマスクが解除される
  2. レイヤーマスクはレイヤーマスク自身のmaskプロパティをnullにすると解除される
  3. レイヤーマスクをaddChildするとマスク自身が表示されなくなる(マスクは解除される)
  4. removeChildしたレイヤーマスクは再度適用するにはaddChildだけでは適用されない、再度maskプロパティを設定する必要がある
  5. removeChildしたレイヤーマスクを再度適用するにはaddChildAtで対象オブジェクトの下に配置する(対象より下なら深度はいくつでもよい)
  6. マスクオブジェクトは、適用時に対象となるオブジェクトのひとつ下の深度に再配置される
  7. マスクオブジェクトは常に対象オブジェクトより下の深度に配置しないと適用されない
  8. マスクオブジェクトは、自身のmaskプロパティに対象オブジェクトが設定される(レイヤーマスクではnullが返る)
なので再利用するときはremoveChildした後でaddChildAt(0)で再配置、もしくはmaskプロパティを再設定するというのが妥当そうです。
マスクオブジェクトと対象オブジェクトの間に別のオブジェクトが存在すると、挟まれたオブジェクト側が表示されなくなるようです。
レイヤーマスクは複数のオブジェクトでマスクを共有できる、という点でスクリプトとは挙動が違うのでいろいろあるのではと思います。(スクリプトではmaskは1つしか設定できないはず)
あとTextFieldにマスクかけるとダイナミックテキストが消えちゃうやつとかもあるし。(これはBlendMode.layerで対応できる)
個人的にマスクオブジェクトは対象を上からマスクするのではなく、自分の上に配置された対象オブジェクトを自分の領域に描画するっていう仕様なのかなぁと推測してます。(細かい仕様まで調べてないのでわからないですけど)
「いや、それ違うよ」とか見落としてる部分があれば教えていただければと思います。

Flashライブラリ内の選択した複数アイテムをフレーム毎に並べるJSFL

2011 年 7 月 26 日 火曜日

最近はタイムライン上であれこれする作業が多いのでいろいろ公開されているJSFLを使う機会が増えました。
んで、ちょっとJSFLについてググッてみたら作れそうだったのでチャレンジ。

ちなみにJSFLとはFlash上で動作するJavaScriptを使用したマクロのような拡張機能です。Flashを使っているならすでに知っている方や使っている方も多いと思います。

今回はFlashライブラリ内の選択したシンボル(画像)をフレーム毎に順に並べていくjsflを作成しました。

設定方法

下記のスクリプトを.jsflの拡張子で保存。保存ディレクトリはFlashのCommandsフォルダ。(OSによって異なるので詳しくは下記参照)

Win
/C/Documents and Settings/アカウント名/Local Settings/Application
Data/Adobe/Flash CS3/ja/Configuration/Commands

Mac
/Users/アカウント名/Library/Application Support/Adobe/Flash CS5.5/ja_JP/Configuration/Commands

//
// ライブラリで選択されている複数アイテムを
// 左上基準で一定フレームごとに配置します
//
// @author 	Tatsuya Kimura
// @date	2011.07.24
//

var el; // ステージ配置後のアイテム(エレメント)

var tl = fl.getDocumentDOM().getTimeline(); //タイムラインを取得
var selected = fl.getDocumentDOM().library.getSelectedItems(); // 選択中のライブラリアイテム配列
var interval = 1; // 配置するフレーム間隔

// エレメントの配置
for(i = 0;i < selected.length;i++){

	// 2回目以降、次のフレームに空白キーフレームを挿入
	if(i){ tl.convertToBlankKeyframes(tl.currentFrame + interval); };

	// 選択中のアイテムを配置
	// ここでは中央基準でアイテムが配置される
	fl.getDocumentDOM().library.addItemToDocument({x:0, y:0}, selected[i].name);

	// 中央基準で配置されたアイテムを左上基準に再配置
	// (アイテムの中央基準で配置したい場合は下記の3行をコメントアウト)
	el = tl.layers[tl.currentLayer].frames[tl.currentFrame].elements[0];
	el.x = 0;
	el.y = 0;

	// 選択中の最後のアイテムになったら
	// 設定した間隔分のフレームを挿入
	if(i == selected.length - 1){
		tl.insertFrames(interval - 1,false,tl.currentFrame + 1);
	};

}

// 処理後に一応全フレームを選択中にしておく
tl.selectAllFrames();

使用方法

保存後にツールパネルのコマンドを開くと保存したjsflのファイル名が表示されます。
コマンドパネル

ライブラリで配置したいシンボル(画像)を全て選択、配置したいフレームの先頭にカーソルを合わせて上記で表示されたコマンドを実行してください。
シンボルを選択

下記のように配置されます。
実行結果

また、下記のスクリプト部分で配置間隔を変更することもできます。


var interval = 4; // 4フレーム毎に配置

実行結果
実行結果

自分の実行環境でCS4の場合、選択したシンボルの末尾が先頭にきてしまうようです。
(多分配列を取得した時点でそうなってるのでバグっぽい)
なのでもしその不具合が出たら手作業でちょちょいっと並び替えてください。

時間がある時に配置の基準点やフレーム間隔をメニューから設定できるようにする予定です。
検証がまだまだ不十分なので不具合とか気づいた点コメントいただけると嬉しいです。

参考サイト

下記サイトを参考にさせていただきました、ありがとうございます!

【Flash 拡張】JSFL MXP まとめ - YAIMO BLOG
http://blog.yaimo.net/jsflmxp/

JSFL入門メモ - プログラマー、再起動中
http://d.hatena.ne.jp/naoto5959/20090402/1238663507

第一回東京ひよこの会に行ってきました。

2011 年 3 月 8 日 火曜日

2011/3/5、第一回東京ひよこの会に参加させていただきました。
東京ひよこの会 (第1回勉強会) レポート

今回自分は、初めてFlashサイトを作った時に苦労した複数ボタン(ナビゲーション)の切替管理を作成しました。
ファイルはShigeru Ogawaさんのページにアップしていただきました。

複数ボタンサンプルページ

Main.as - ドキュメントクラス
ButtonManager.as – ボタンの状態を監視するクラス
Button.as – ボタン用クラス

1.ButtonManagerクラス がそれぞれのボタンのクリックイベントを監視
2.クリックされたボタンはそのままアクティブに
3.ButtonManagerはクリックされていないボタンを探してリセットする

という構造になっています。(ソースコードは割愛します)

ところで。。
勉強会の参加は今回初めてでしたが、ほんと参加して良かった!

色々な方の発表を聞いて、作り方を見て、普段気づかなかったことや、新しい視点に気づくこともできた。
それと、発表するってあらためて難しいなぁと感じた。(自分は全然ちゃんと発表できてなかった。。。 泣)

そしてあらためてFlashは楽しいなぁ、と感じた。

「いまさら他人に聞けないFlashの基礎的な何かを勉強する会。」
これってほんと深いお題だなぁと思いました。

色々ご用意していただきましたc_geru さん、poyosi さん、SIHO_o さん、sakusan393 さん、ありがとうございました。
また今後も参加したいなぁと思ってます。

IEでFlashが表示されない場合

2011 年 1 月 29 日 土曜日

IEでFlashが表示されないバグがつい先日ありました。すぐに解決できたのですが似たような例が割と多いようなので、今回自分が気づいた解決法をメモ。

結論から言うとhtmlソースの文字コード指定(charset)の記述が間違っていただけ。(バグと言うかミス)

IEは文字コードが指定されない場合、Shift_jisとしてエンコーディングしようとします。そのためHTMLソース内で文字化けが起こり、Flashの呼び出しが正常に動作せず表示されなくなったわけです。。。

ただ、他のFlashで同様に試してみたら、表示はおかしいけれど呼び出しはされていたので、他にも原因がありそう。。。
とりあえずIEでFlashが表示されない場合は文字コードまわりを一度チェックしてみることをオススメします。

他のかたの記事でこんな事例もありました。やっぱり文字コードまわり
http://wintercave.com/blog/?p=344#respond

Box2Dの練習がてら時計

2010 年 12 月 6 日 月曜日

触ろう触ろうと思ってなかなか触っていなかったBox2Dにやっと手をつけました。
あとで手順的なものを書きたいと思いますけど、ひとまず作ったものだけアップしておきます。

[Box2D]いちおう時計 – wonderfl build flash online

パーティクル時計

2010 年 12 月 6 日 月曜日

時計ものを作ったことがなかったので、ぱっと思いついたのを作ってみました。
でも処理が少し重いし雑。

ParticleClock – wonderfl build flash online

カメラ映像で動体検知を描画する

2010 年 11 月 3 日 水曜日

インスタレーションぽい案件でカメラの画像処理をいろいろと試していたのでその時のリソースをwonderflで再編集してみました。

動体検知?Physical Bitmap – wonderfl build flash online

動体検知?その2[上塗り版]Physical Bitmap – wonderfl build flash online

ループ関連の処理速度の高速化

2010 年 2 月 12 日 金曜日

海外のこんな記事に行き着いた。

More performance tuning in Actionscript 3

http://www.danielhai.com/blog/?p=55

パフォーマンスの違いは確かにわかるけど、根本的に比較する条件が違うよーな気がする。

続・XMLのロードでnullが返ってくる(解決)

2010 年 2 月 11 日 木曜日

前回のエントリー「XMLのロードでnullが返ってくる」で as 演算子と クラス名(target)の違いについて調べてみた。

as演算子によるとキャストできなかった場合にnullが返ってくるかエラーになるかの違いらしい。
でも前回の場合、as の場合はnull で括弧を使った場合は読み込めるっていう感じだった。

あ、野中さんの記事発見。

as演算子は、キャストに利用することができます。ただし、データ自体を変えることはありません。データを変更しなければデータ型が変換できない場合には、nullを返します。

ていうことは、、、

あぁ、やっと気づいた。
つーかURLLoaderでテキストで読み込んでるんだからStringだよね。
バカバカバカ!!!

通常はこうするのね。

function init():void
{
	var l:URLLoader = new URLLoader();
	l.addEventListener(Event.COMPLETE,onLoadComplete);
	l.load(new URLRequest("tinco.xml"));
}

function onLoadComplete(e:Event):void
{
	var xml:XML = new XML(e.target.data);
}

あふぉーなオレはこうしていました。

function init():void
{
	var l:URLLoader = new URLLoader();
	l.addEventListener(Event.COMPLETE,onLoadComplete);
	l.load(new URLRequest("tinco.xml"));
}

function onLoadComplete(e:Event):void
{
	var xml:XML = XML(e.target.data); // これでも一応XMLに変換できたけど
}

対象ファイルの拡張子とか中身がXML表記でも読み込まれた時はString型なわけ。
URLLoaderのロードしたデータがString型なのに「これはXMLだ!」って言いはっていたわけ。
as演算子を使うとそんなウソは通用しません!っていうことで一件落着。

ちなみにこの記事「【AS3入門】as演算子とカッコ()を使ったキャストの違いCommentsAdd Star」はとても参考になりました。

XMLのロードでnullが返ってくる

2010 年 2 月 11 日 木曜日

しょーもないことでしばしばつまづいてしまうのでメモ。

URLLoaderでXML読み込んで、Event.target.dataでXMLを取得する場合。

 
function init():void
{
	var l:URLLoader = new URLLoader();
	l.addEventListener(Event.COMPLETE,onLoadComplete);
	l.load(new URLRequest("tinco.xml"));
}
 
function onLoadComplete(e:Event):void
{
	// 誤
	var xml:XML = e.target.data as XML;
	trace(xml) // null

	// 正
	var xml:XML = XML(e.target.data);
	trace(xml) // xmlがちゃんと返ってくる
}

キャストで クラス名() っていうのと as クラス名 ってのの違いをイマイチ理解していない。
他でも同じようなことがたまにあるからちゃんと調べよ。