[as3]超簡単flashにコ◯ミコマンドを仕込む方法

古の少年心を呼び覚ますおふざけギミックをFLASHに仕込んでみるメモです。

まずは完成品と、完成スクリプトを

var my_command:String;

stage.addEventListener(KeyboardEvent.KEY_DOWN,fnc_keydown);
function fnc_keydown(event:KeyboardEvent):void{

	IME.enabled = false;
	my_command += event.keyCode; //判定を保存

	ins_keycode.text = String(event.keyCode); //KEYCODEフィールドに文字を表示
	ins_unicode.text = String.fromCharCode(event.charCode); //UNICODEフィールドに文字を表示
	ins_total.appendText( String(event.keyCode) ); //TOTALINPUTフィールドに文字を表示

	if( event.keyCode == Keyboard.ENTER ){ //エンターを押したら実行
		if( my_command == "3838404039373937666513" ){ //↑↑↓↓→←→←BAだったら
			ins_total.text = "COMMAND SUCCESS!!";
			ins_ufo.ins_ufo_core.gotoAndStop( 2 );
		} else {
			ins_total.text = "COMMAND FAILED...";
			ins_ufo.ins_ufo_core.gotoAndStop( 1 );
		}
	}
	my_command = ""; //判定初期化

}

では、順を追って作成方法を説明していきます。

【1】必要なリソースを用意

◆asレイヤー:上記のスクリプトをコピペ(詳細は【3】以降で)
◆mcレイヤー:後述
◆textレイヤー:ダイナミックテキストを3つ配置。それぞれ…”ins_total”、”ins_keycode”、”ins_unicode”というインスタンス名を付けましょう。
◆bgレイヤー:宇宙の背景。無くてもいい
【2】コマンド成功時にムービークリップが変化するように

mcレイヤーに配置されているmcは入れ子になってて、以下みたいなカンジです。

◆mc_ufo(ufoが1個ふわふわしてるだけ、インスタンス名はins_ufo_core)

◆mc_ufo_core
1フレーム目→UFOが1個だけ配置(静止画)
2フレーム目→UFOと、オプションUFO(mc_ufo_option)いっぱい

ちなみにmc_ufo_coreのフレームの見た目は以下のカンジ

【3】判定用の変数作成

まず、コマンドが成功したかを判定するための変数を作ります。ストリング型で。

var my_command:String;
【4】イベント登録

次にステージ全体に対してキーボードイベントを登録します。イベント対象は”キーボードが押されたら”(KEY_DOWN)。イベントが実行された実行される関数はfnc_keydownとします。

stage.addEventListener(KeyboardEvent.KEY_DOWN,fnc_keydown);
function fnc_keydown(event:KeyboardEvent):void{}
【5】判定開始&文字列を蓄積

fnc_keydown関数の中に処理を記述していきます。

まず、念のためにユーザーの入力モードを半角英数モード(IME無効化)にします。

IME.enabled = false;

次にさっき作った”my_command”の中に代入演算子”+=”で、入力したキーコードを格納していきます。

my_command += event.keyCode; //判定を保存
【6】デバッグ用処理(実装時には無くてもいいです)

fnc_keydown関数の中に処理を記述していきます。

ちなみにこの記述はコマンドの成否に全然関係ないです、入力状況を監視したい時用なカンジです。実装する時には不要でしょうね。

ins_keycode.text = String(event.keyCode); //KEYCODEフィールドに文字を表示
ins_unicode.text = String.fromCharCode(event.charCode); //UNICODEフィールドに文字を表示
ins_total.appendText( String(event.keyCode) ); //TOTALINPUTフィールドに文字を表示

KeybordEventの値を取得して、それぞれ…event.keyCodeで入力されたキーボードのキーコード、event.charCodeで入力されたキーの文字列…はそのままは取得できないんで(文字コードに割り当てられた数字が出ちゃうので)String プロパティにある、「()内のコードのUnicode(2バイト文字の統一規格)を返すメソッド」であるfromCharCodeメソッドを使って…String.fromCharCode(event.charCode)と記述すれば、理論上は値が取れます(IMEがONだと変な挙動するけど)。

で、最後に入力したキーコードを全部出す記述も出力(成否の確認のためみたいな)。

【7】成否判定

ここがコア、ここで判定してます。

if( event.keyCode == Keyboard.ENTER ){ //エンターを押したら実行
	if( my_command == "3838404039373937666513" ){ //↑↑↓↓→←→←BAだったら
		ins_total.text = "COMMAND SUCCESS!!";
		ins_ufo.ins_ufo_core.gotoAndStop( 2 );
	} else {
		ins_total.text = "COMMAND FAILED...";
		ins_ufo.ins_ufo_core.gotoAndStop( 1 );
	}
	my_command = ""; //判定初期化
}

まずif文で押されたキーコードと、ENTERボタンが押された場合の定数(Keyboard.ENTER)を比較して、押されてた場合のみコマンドをチェックするようにします。

次にさらにif文をかいて、my_commandと”↑↑↓↓→←→←BA”のキーコードである”3838404039373937666513″を比較します。
もし達成していたらデバッグテキストに”COMMAND SUCCESS!!”と出力しつつ、ins_ufoと名の付いたムービークリップの中にあるins_ufo_coreのタイムラインをgotoAndStop( 2 )で2フレーム目に移動させてUFOのムービークリップを変化させます。

逆にコマンドが達成してなかったらデバッグテキストに”COMMAND FAILED…”と出して、UFOのムービークリップを初期化(1フレーム目に移動)させます。

また、コマンドが成功しててもしてなくても、最後にコマンドを初期化します。

以上です。キーボードイベントは思ってたよりもシンプルだったので、配列かswitchと組み合わせればタイピングゲームとかも作れそうですね。

ドット素材:フリーWEB素材サイト「DOTS DESIGN(ドッツ・デザイン)」様
参考文献:Adobe ActionScript 3.0 コンポーネントリファレンスガイド
参考文献:Adobe Flash Platform キーボード入力のキャプチャ
参考文献:FlashゲームPG講座 For AS3.0【キーボードの操作について】

カテゴリー: FLASH | タグ: | コメントは受け付けていません。

[WEBDESIGN:FLASH]フルflashサイトでもGoogleAnalyticsでサイトをまたいだ解析をしたい

フルflashサイト(以下フルフラ)じゃない普通のサイトのサイトをまたいだ解析(以下クロスドメイン解析)をしたい人や、そもそも「クロスドメイン解析ってなあに?」って人はこちら

基本的には普通のサイトのやりかたと一緒ですが、アンカーの扱いが違います。

まずやり方

【STEP1】トラッキングコードを取得

通常と同じようにトラッキングコードを取得。

◆GoogleAnalyticsログイン≫アナリティクス設定をクリック≫トラッキングコードのタブをクリック≫画面下のほうにトラッキングコードがある

<script type="text/javascript">

	var _gaq = _gaq || [];
	_gaq.push(['_setAccount', 'UA-◯◯◯◯◯◯◯◯-◯']);
	_gaq.push(['_trackPageview']);

	(function() {
		var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
		ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
		var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
	})();

</script>

※「◯」の部分にはそれぞれのユーザー専用の「トラッキングID」が入ります

【STEP2】複数サイト専用のメソッドを追記する
  • ドメイン名を保持するか:_gaq.push(['_setDomainName', '値']);(値はnoneで)
  • クッキーにリファラを保持するか:_gaq.push(['_setAllowLinker', 値]);(値はtrue)
<script type="text/javascript">

	var _gaq = _gaq || [];
	_gaq.push(['_setAccount', 'UA-◯◯◯◯◯◯◯◯-◯']);
	_gaq.push(['_setDomainName', 'none']);
	_gaq.push(['_setAllowLinker', true]);
	_gaq.push(['_trackPageview']);

	(function() {
		var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
		ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
		var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
	})();

</script>

※「◯」の部分にはそれぞれのユーザー専用の「トラッキングID」が入ります

【STEP3】flash側にクリックイベントを設定
ボタンのインスタンス名.addEventListener(MouseEvent.CLICK,function():void{
	navigateToURL( new URLRequest( "javascript:fnc_analysis( '" + "飛び先のURL" + "')" ),"_self" );
});

イベントと関数を無名関数でまとめてますけど、分離して書いてるなら以下。

ボタンのインスタンス名.addEventListener(MouseEvent.CLICK,関数名)
function 関数名(e:Event):void{
	navigateToURL( new URLRequest( "javascript:fnc_analysis( '" + "飛び先のURL" + "')" ),"_self" );
}

ボタンをクリックすると、html側の”fnc_analysis”っていう関数が実行されます。

【STEP4】html側にトラッキングコードを記述

STEP2で改造したトラッキングコードをhtmlの<head>の中に記述します。

<html>
<head>
<script type="text/javascript">

	var _gaq = _gaq || [];
	_gaq.push(['_setAccount', 'UA-◯◯◯◯◯◯◯◯-◯']);
	_gaq.push(['_setDomainName', 'none']);
	_gaq.push(['_setAllowLinker', true]);
	_gaq.push(['_trackPageview']);

	(function() {
		var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
		ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
		var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
	})();

</script>
</head>
<body>
<!--ページの内容-->
</body>
</html>

※わかりやすくするためにDTDとか一切省いてます。実際はちゃんと入れてください。

【STEP5】html側にflashから呼び出される関数を記述
<!--analysis_js-->
<script>
function fnc_analysis( url ){window.open(_gat._getTrackerByName()._getLinkerUrl(url),'_blank');}
</script>
<!--/analysis_js-->

STEP4と合わせるとこんなかんじ。

<html>
<head>
<script type="text/javascript">

	var _gaq = _gaq || [];
	_gaq.push(['_setAccount', 'UA-◯◯◯◯◯◯◯◯-◯']);
	_gaq.push(['_setDomainName', 'none']);
	_gaq.push(['_setAllowLinker', true]);
	_gaq.push(['_trackPageview']);

	(function() {
		var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
		ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
		var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
	})();

</script>
<!--analysis_js-->
<script>
function fnc_analysis( url ){window.open(_gat._getTrackerByName()._getLinkerUrl(url),'_blank');}
</script>
<!--/analysis_js-->
</head>
<body>
<!--ページの内容-->
</body>
</html>

“fnc_analysis”関数は念のためGoogleのトラッキングコードの後に書いてください。”fnc_analysis”の中に記述されているメソッドはトラッキングコードで呼び出されているAPIのメソッドだからです(存在しない関数を呼び出す事になるので動作しなくなります)。

ちなみに新規ウィンドウをポップアップするようにしてますが、もしポップアップさせたくない場合はSTEP5の”fnc_analysis”関数の中身を以下のように書き換えてください。

<!--analysis_js-->
<script>
function fnc_analysis( url ){onclick="_gaq.push(['_link','url']);}
</script>
<!--/analysis_js-->

あとURLをflash側に持ちたくない場合はflashにxmlを読み込んで処理するといいでしょう。複数ヶ所にリンクがある場合や、サイト全体にswfファイルが分散している場合に一つのxmlの記述を直せば済むので。

もしxmlを使ったやり方をポストして欲しい人がいればtwitterまでお声がけいただければと思います。

カテゴリー: FLASH, WEB DESIGN | タグ: | コメントは受け付けていません。

[WEBDESIGN]GoogleAnalyticsでサイトをまたいだ解析をしたい

サイトをまたいだ解析(クロスドメイン解析)をするためのメモ。まずは概要です。

また、flashサイトの場合はこちらをどうぞ。

概要
トラッキングコードは最新版の非同期コードを使用
サイトAとサイトBという2つのサイトを管理しているような状況
サイトAとサイトBはそれぞれ別のトラッキングコードで、別々にレポートを管理している
広告→サイトA→サイトB→サイトBのコンバージョンページ…と遷移した場合にサイトBのレポートで広告のリファラが取りたい

手順を説明していきます。

【STEP1】トラッキングコードを取得

まずGoogleAnalyticsにログインし、右上の「アナリティクス設定」をクリックします。

次に「トラッキングコード」のタブをクリックし、画面を下にスクロールすると以下のような文字列が書いてあるはずです。これがトラッキングコードです。

<script type="text/javascript">

	var _gaq = _gaq || [];
	_gaq.push(['_setAccount', 'UA-◯◯◯◯◯◯◯◯-◯']);
	_gaq.push(['_trackPageview']);

	(function() {
		var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
		ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
		var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
	})();

</script>

「◯」の部分にはそれぞれのユーザー専用の「トラッキングID」が入ります。

【STEP2】複数サイト専用のメソッドを追記する

以下の2つのメソッドを追記します。

  • ドメイン名を保持するか:_gaq.push(['_setDomainName', '値']);(値の部分にはドメイン名が入ります。たとえばwrelish.comなど)
  • クッキーにリファラを保持するか:_gaq.push(['_setAllowLinker', true]);(これがキモです。falseなら保持しない。trueなら保持します)

クロスドメイン解析をするための値を記述して、メソッドを追記すると以下のようになります。

<script type="text/javascript">

	var _gaq = _gaq || [];
	_gaq.push(['_setAccount', 'UA-◯◯◯◯◯◯◯◯-◯']);
	_gaq.push(['_setDomainName', 'none']);
	_gaq.push(['_setAllowLinker', true]);
	_gaq.push(['_trackPageview']);

	(function() {
		var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
		ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
		var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
	})();

</script>

GAのディフォルト「複数のトップレベル ドメイン」でトラッキングコードを発行すると「_gaq.push(['_setDomainName', 'none']);」のnoneの箇所に管理サイトのドメイン名が自動的に入りますが、クロスドメイン解析をする際にはnoneにしてください(Googleの公式ヘルプにもそう載っています)。

【STEP3】サイト間を移動するリンクにスクリプトを仕込む

◆同一ウィンドウ版:

<a href="リンク先URL" onclick="_gaq.push(['_link','リンク先URL']);return false;">リンクテキスト</a>

◆新規ウィンドウ版:

<a href="リンク先URL" onclick="window.open(_gat._getTrackerByName()._getLinkerUrl('リンク先URL'),'_blank');return false;">リンクテキスト</a>

ソース構造見る限り非同期コードは配列に値をpushしてくタイプみたいですね。

ちなみにブランクウィンドウを開くソースはonclickでwindow.openというjavascriptを起動してGAのAPIのメソッドでリンクを起動します。その際javascriptが動かないブラウザだった場合には通常のhrefのリンク先が起動するので、アクセスに問題は出ません(逆にjavascriptが動くブラウザならreturn falseが動き、href属性を無効化するので通常のtarget=”_blank”などを入れる意味はありません/動作しません)。

以下メソッドには関係のない雑記です。

無料のアクセス解析ツールとしては…いや、無料じゃないアクセス解析ツールと比べても非常に高性能なGoogleAnalytics(以後GA)。

単体のサイトをアクセス解析するのはGoogleアカウントを取得してトラッキングコードを埋め込めばとりあえずはOKですが、ECサイトやポータルサイトとなってくると上記のようにちょっとした工夫が必要です。

ECサイトやポータルは大抵の場合コンバージョン(成果目標)を定めます。

コンバージョンとは、ECサイトならショッピングカートの決済完了画面、ポータルサイトなら会員登録完了画面などがそれに当たるとおもいます。

コンバージョンを設定すると、そのコンバージョンがどの経路をたどってきたかが気になります。

例えば広告媒体A、例えばCPC広告B、GoogleAnalyticsは「そのアクセスがどこから来たか?」(リファラと言います)そんなデータも表示してくれますが、通常のままだと「直前のリファラ」しか表示できません。

つまり以下のような場合は両方が自分の管理サイトであっても(トラッキングコードを埋め込めても)リファラが正確に見えないのです。

  1. 広告媒体のバナーをクリック
  2. “管理サイトA”にアクセス
  3. “管理サイトA”から”ポータルサイトB”の登録フォームへ
  4. “ポータルサイトB”の会員登録完了画面(コンバージョン)へ

こうなってしまうと”ポータルサイトB”のコンバージョンには、”管理サイトA”のリファラしか残りません。

本当は広告を経由して来ているはずなのに、別のサイトなのでデータが引き渡せてないのです。これではCVRが出せず、費用対効果が分かりません。

そうなってしまう前に、きちんと設定して有効な広告運用を心がけたいですね。

カテゴリー: WEB DESIGN | タグ: | コメントは受け付けていません。

[as3]ステージより大きい画面をクリック&ドラッグ出来るflash

画面外に何かがあって、クリック&ドラッグでその位置を「グイッ」とひっぱれるflashをよく見かけるので、どうやってるのかなぁとググッたけど見つからなかったので適当にやってみました。

対象オブジェクトと表示範囲を動的に取ろうとしてるから行数多いですが、実際はすごくシンプルでした。

手順は以下。

  1. ファイル作る
  2. ナビゲーションとかグラフィックとかをひとまとめにしたmc、ないしは外部からロードしたswfをステージの中央に配置する(動的でもOKです)。
  3. 配置したオブジェクトにインスタンス名”ins_mainstage”を付ける(外部からロードしてるのであれば配置する変数名を”ins_mainstage”に)。
  4. 以下に記載するソースを配置されたフレームに記述(別レイヤーでも一緒でもご自由に/ボクは別にしてます)。
/*
グローバル変数の作成
*/
var rec_maxx:int = stage.stageWidth - ins_mainstage.width / 2;
var rec_maxy:int = stage.stageHeight - ins_mainstage.height / 2
var rec_maxwidth:int = ins_mainstage.width - stage.stageWidth;
var rec_maxheight:int = ins_mainstage.height - stage.stageHeight;
var rec_mainstage:Rectangle = new Rectangle(rec_maxx,rec_maxy,rec_maxwidth,rec_maxheight);

/*
マウスイベント
*/
//ダウンイベント(クリック維持状態で発生)
stage.addEventListener(MouseEvent.MOUSE_DOWN,function():void{
	ins_mainstage.startDrag(false,rec_mainstage);
});

//アップイベント(クリック維持状態≫離した瞬間発生)
stage.addEventListener(MouseEvent.MOUSE_UP,function():void{
	ins_mainstage.stopDrag();
});

//リーブイベント(画面外にマウスが移動したら発生)
stage.addEventListener(Event.MOUSE_LEAVE,function():void{
	ins_mainstage.stopDrag();
});

パブリッシュの段階で表示範囲のチェックがしたい場合には以下を追記するとわかりやすいです。

/*
debug用表示範囲
*/
var sp_rec_stagearea:Sprite = new Sprite();
sp_rec_stagearea.graphics.beginFill(0xFF0000);
sp_rec_stagearea.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
sp_rec_stagearea.alpha = 0.5;
addChild( sp_rec_stagearea );

ステージ自体の幅とか、配置するmc(ないしはswf)のサイズは動的に取るのでいちいちサイズ入れる必要はないです。
(※ただし外部swfの場合ロード完了させておいて、かつ参照プロパティの前にcontent入れないとですが)

あとは動きの部分のトゥイーン付けたりすればもっとリッチですね。

カテゴリー: FLASH | コメントは受け付けていません。

[as3]クリックイベントをもっとまとめてみた

actionscript3のクリックイベントをまとめてみた、前回のポストはこちら

グローバルナビゲーションとか、ローカルナビゲーション程度だけで、そんなにボタンが多くないのをまとめるだけなら上記のポストで十分ですが、もしこれがギャラリー系でサムネイルが大量にあったら面倒になってきます。

対象を判定するために、オブジェクトにインスタンス名(ないしは動的に生成してるなら変数名)は必ず付くんですが、それと対になる形でイベントを全部記述してると、場合によっては100行ぐらいになっちゃうことも…。

そんな時にさっくりまとめる方法を思いついたのでポストしてみます。
まずはわざと面倒に書いて、そのあとにまとめてみたバージョンを書いていきます。

わざと面倒に書いたバージョン
stage.addEventListener(MouseEvent.CLICK,fnc_click); //ステージに対してクリックイベントを登録
function fnc_click( e:Event ):void{

	switch( e.target.name ){ //クリックされた対象のインスタンス名で処理を振り分け

		case "ins_thamb_1" :
		trace( "サムネイル1がクリックされた" );
		break;

		case "ins_thamb_2" :
		trace( "サムネイル2がクリックされた" );
		break;

		case "ins_thamb_3" :
		trace( "サムネイル3がクリックされた" );
		break;

	}

}

こんなかんじで、インスタンス名(変数名)をキーとしてクリックされた対象を記述していく必要があるかと思われます。

まとめてみたバージョン
stage.addEventListener(MouseEvent.CLICK,fnc_click); //ステージに対してクリックイベントを登録
function fnc_click( e:Event ):void{

	var my_array_split:Array = String( e.target.name ).split( "_" ); //対象のインスタンス名を引数の文字列を条件(この場合はアンダースコア)にして分解して配列に格納

	switch( e.target.name ){ //クリックされた対象のインスタンス名で処理を振り分け

		case "ins_thamb_" + my_array_split[2] :
		trace( "サムネイル" + my_array_split[2] + "がクリックされた" );
		break;

	}

}

クリックした対象の名前をキーとするのは同じなんですが、それをsplitメソッドで分解、それと同時に配列に格納します。
たとえば”ins_thamb_1″という名前の付いたインスタンスをクリックしていた場合…

  • “ins”はmy_array_split[0]
  • “thamb”はmy_array_split[1]
  • “1″はmy_array_split[2]

のように格納されます。

で、これをどう使うか。
ギャラリーの場合、だいたい画像をポップアップしたりすると思うのですが、その画像のURL管理などにxmlや配列を使うとおもいます。
例えば以下のように。

//xmlは"xml_config"というXMLオブジェクトにロード完了しているものとします
/*
【xml】
<xml>
	<imagenode url="iamge1.jpg"></imagenode>
	<imagenode url="iamge2.jpg"></imagenode>
	<imagenode url="iamge3.jpg"></imagenode>
</xml>
*/
var my_array_img:Array = new Array(); //画像URL格納用の配列を作成
for( var i:int; i < xml_config.imagenode.length(); i++ ){ //imagenodeノードの数だけ処理
	my_array_img[i] = xml_config.imagenode[i].@url; //配列にurlを格納
}

その際にインスタンス名を分解して配列に格納する仕組みがあれば、直上記"my_array_img"配列の番地指定(配列名[番地])に活用できます。
具体的なサンプルは以下です。

stage.addEventListener(MouseEvent.CLICK,fnc_click); //ステージに対してクリックイベントを登録
function fnc_click( e:Event ):void{

	var my_array_split:Array = String( e.target.name ).split( "_" ); //対象のインスタンス名を分解して配列に格納
	var target1:int = my_array_split[2];

	switch( e.target.name ){ //クリックされた対象のインスタンス名で処理を振り分け

		case "ins_thamb_" + target1 :
		trace( "サムネイル" + target1 + "がクリックされた" );
		trace( my_array_img[target1] + "をどうこうする" ); //サムネイルの名前の数字を使って番地指定。もしins_thamb_1をクリックしていたら"my_array_img[1]"をどうこうする。
		break;

	}

}

もしギャラリーがflash内の複数のページにある場合には2次元配列を使うといいでしょう。
その場合はサムネイルのインスタンス名を少し工夫します。

たとえばコンテンツ1の1個目のサムネイルなら、"ins_thamb_1_1"など。そして、xml構造を少し修正し、画像URLを格納する配列は二次元化します。

//xmlは"xml_config"というXMLオブジェクトにロード完了しているものとします
/*
【xml】
<xml>
	<parentnode>
		<imagenode url="iamge_1_1.jpg"></imagenode>
		<imagenode url="iamge_1_2.jpg"></imagenode>
		<imagenode url="iamge_1_3.jpg"></imagenode>
	</parentnode>
	<parentnode>
		<imagenode url="iamge_2_1.jpg"></imagenode>
		<imagenode url="iamge_2_2.jpg"></imagenode>
		<imagenode url="iamge_2_3.jpg"></imagenode>
	</parentnode>
	<parentnode>
		<imagenode url="iamge_3_1.jpg"></imagenode>
		<imagenode url="iamge_3_2.jpg"></imagenode>
		<imagenode url="iamge_3_3.jpg"></imagenode>
	</parentnode>
</xml>
*/
for( var i:int; i < xml_config.parentnode.length(); i++ ){ //親ノードの数だけ処理
	my_array[i] = new Array(); //親ノードの数だけ2次元配列を作成
	for( var ii:int = 0; ii < xml_config.parentnode[i].imagenode.length(); ii++ ){ //現在処理中の子ノードの数だけ格納
		my_array[i][ii] = xml_config.parentnode[i].imagenode[ii].@url;
	}
}

その上で以下のように実行すれば複数ページも以下の処理で全てまとめられます。

stage.addEventListener(MouseEvent.CLICK,fnc_click); //ステージに対してクリックイベントを登録
function fnc_click( e:Event ):void{

	var my_array_split:Array = String( e.target.name ).split( "_" ); //対象のインスタンス名を分解して配列に格納
	var target1:int = my_array_split[2];
	var target2:int = my_array_split[3];

	switch( e.target.name ){ //クリックされた対象のインスタンス名で処理を振り分け

		case "ins_thamb_" + target1 :
		trace( "サムネイル" + target1 + "がクリックされた" );
		target1--; //配列は0からなので1引く
		target2--; //配列は0からなので1引く
		addChild( my_array_img[target1][target2] );
		break;

	}

}

以上です。
それなりに便利に感じるので、もし「使えるかも」と思った方はぜひ試してみてください。

カテゴリー: FLASH | タグ: | コメントは受け付けていません。

[as3]FLASHで音声を再生ボタンを複数用意してみよう

単純に音声を鳴らすだけなら前回のポストをご覧ください。

まず完成品をペタリ。


音声再生を複数配置するのはいろんなシーンで出てくると思います。その際に問題になる「Aの再生中にBが押されたら、Aの再生中にもう一度Aが押されたら…」といった複数再生時の時の処理を織り込んだプログラムを書いていきます。

では以下より手順を追って作成していきます。

【1】ファイルを用意する

上記のようにファイルを準備します。今回mp3はVoicePro様のフリー音源をお借りしました。

複数ファイルを呼び出す時に便利なのと、複数処理に便利なので設定ファイルとしてxmlも用意します。

【2】レイヤー&フレームを用意

全てrootです。上から順に…

loading:いまローディング中です。をわかりやすく伝えるためのローディング画像(と進捗を表示するダイナミックテキストがセットになったMC)。

button:ボタンシンボル×5個。配置したいmp3のぶんだけ置くといいでしょう。

as/loading:swf自身のローディングと設定ファイル(config.xml)をロードするスクリプトを記述します。2フレーム目でxmlのデータを扱うので1フレーム目に記述します。

as/main:クリックイベントや再生制御などメインの処理を記述します。xmlのデータを扱うので確実にロードが完了している2フレーム目に記述します。

【3】ローディングムービークリップを配置

1フレーム目にローディング中を表すムービークリップを配置します。

子の構成は「ローディング画像(動画でもOK)」と「進捗を表示するダイナミックテキスト」です。

ムービークリップには”ins_nowloading”というインスタンス名を、その子にあるダイナミックテキストには”ins_loadtxt”というインスタンス名を付けてください。

【4】ボタンシンボルを作成

音声再生のトリガーとなるボタンシンボルを配置していきます。

適当に一つ作ってライブラリパネルで複製・一部変更で5個作ってステージに配置していきます。

インスタンス名で判定するので、それぞれ連番のインスタンス名を付けていきます。

【5】インスタンス名を付ける

上記スクリーンショットのようにムービークリップやボタンシンボルをクリックするとプロパティパネルにインスタンス名を入力するフィールドが表示されます。

ここにインスタンス名を入れましょう。インスタンス名はインスタンス名であることをプログラム中にわかりやすくするために命名ルールを決めて付けていきましょう。

ボクの場合は”ins_”と頭につけています。

【6】設定ファイルを作成する

xmlを設定ファイルとして使います。

as側でのコーディングが楽になるようにノード(独自タグ)はわかりやすくシンプル、かつ短いものを付けていきます。この際voice01、voice02と連番のタグにする必要はありません。as側でパースすることが出来るからです。

ノードの中身には音声ファイルまでのパスを記述してください。この際のパスは”xmlファイルやswfファイルから音声ファイルまでのパス”ではなく、”swfが表示されるhtmlから音声ファイルまでのパス”となる事に注意してください。

【7】ローディング処理を作る

swf自体のローディングと、設定ファイルの事前ロードのためにローディング処理を作っていきます。具体的なソースコードは以下です。

this.stop(); //2フレーム目に行かないようにまず止める

//XML用変数
var loader_xml:URLLoader = new URLLoader(); //xmlをロードするローダー
var my_XML:XML; //xmlを格納するflash側のXMLオブジェクト

//イベント登録
loaderInfo.addEventListener(ProgressEvent.PROGRESS, fnc_prog); //読み込み中
loaderInfo.addEventListener(Event.COMPLETE, fnc_comp); //読み込み完了

//読み込み中のイベント
var per:int; //進捗%を表示するための変数
function fnc_prog(e:ProgressEvent):void { //プログレスイベント毎に実行する
	per = e.bytesLoaded / e.bytesTotal * 100; //百分比でバイト総数と現在値を%に
	ins_nowloading.ins_loadtxt.text = String( per ) + "%"; //算出した%をダイナミックテキストに出力
}

//読み込み完了時のイベント
function fnc_comp(e:Event):void {
	loaderInfo.removeEventListener(ProgressEvent.PROGRESS, fnc_prog); //プログレスイベント削除
	loaderInfo.removeEventListener(Event.COMPLETE, fnc_comp); //コンプリートイベント削除
	loader_xml.load( new URLRequest( "config.xml" ) ); //設定ファイルロード開始
	loader_xml.addEventListener( Event.COMPLETE, fnc_xml_config ); //設定ファイルコンプリートイベント登録
}

//設定ファイル読み込み完了時のイベント
function fnc_xml_config(e):void{
	loader_xml.removeEventListener( Event.COMPLETE, fnc_xml_config ); //設定ファイルコンプリートイベント削除

	XML.ignoreWhitespace = true; //プログラムで邪魔になるXMLの余計な空白を削除
	my_XML = new XML(loader_xml.data); //6行目で作った変数にロードしたxmlの中身を入れる

	removeChild( ins_nowloading ); //ローディングオブジェクトを削除
	gotoAndStop( 2 ); //全てがロード完了したので2フレーム目に移動
}

ややこしいように見えるかもしれませんが、swf自身をロードして、終わったら設定ファイルをロードして、2フレーム目に移動する。それだけです。

【8】クリックイベントと音声再生処理を記述していく

まずはクリックイベントから。ボタンごとにイベントを設定すると煩雑なので、ステージ全体をイベントの対象として、クリックされた対象のインスタンス名で処理を振り分けます。自分はこのやりかたが効率が良いと思っていますが、他にもっといい方法があればそれでもいいと思います(我流なので何かお作法がおかしいかもしれません)。

“fnc_playsound”という関数がありますが、これは音声再生用の関数です、次の項目で説明していきます。

/*
クリックイベント
*/
stage.addEventListener(MouseEvent.CLICK, fnc_click); //ステージ自体にクリックイベントを登録
function fnc_click(e:Event):void{

	switch( e.target.name ){ //クリックされた対象のインスタンス名で処理を振り分け

		case "ins_btn01" :
			trace( "Voice01再生ボタンをクリックした" );
			fnc_playsound( 0 );
			break;

		case "ins_btn02" :
			trace( "Voice02再生ボタンをクリックした" );
			fnc_playsound( 1 );
			break;

		case "ins_btn03" :
			trace( "Voice03再生ボタンをクリックした" );
			fnc_playsound( 2 );
			break;

		case "ins_btn04" :
			trace( "Voice04再生ボタンをクリックした" );
			fnc_playsound( 3 );
			break;

		case "ins_btn05" :
			trace( "Voice05再生ボタンをクリックした" );
			fnc_playsound( 4 );
			break;

		default :
			trace( "設定外の対象をクリックした" );
			break;

	}

}

次に音声再生の処理を記述していきます。

/*
サウンドセット
*/
//サウンド用グローバル変数
var array_sound:Array = new Array(); //複数作るサウンドオブジェクトを格納する配列
var array_ch:Array = new Array(); //サウンドオブジェクトと対になり同じだけ必要になるサウンドチャンネルを格納する配列
var my_evesound:int; //現在再生している音声を判定するための変数

//ボイスを呼び出し
function fnc_sound_read():void{ //音声をロードして一回再生しておく(そうしないと以後の処理で扱いにくい)
	for( var i:int = 0; i < my_XML.sound.voice.length(); i++){

		//ロードして配列に格納
		array_sound[i]  = new Sound( new URLRequest( my_XML.sound.voice[i] ) ); //xmlをパースしてパスを抜き出してインスタンス化して作成
		array_ch[i] =  new SoundChannel; //サウンドチャンネルをインスタンス化して作成

		//エラー回避の為に一回再生して停止
		array_ch[i] = array_sound[i].play(); //再生
		array_ch[i].stop(); //停止

	}
}
fnc_sound_read();

/*
再生メソッド
*/
function fnc_playsound( arg_voice01:int ):void{
	my_evesound = arg_voice01; //引数からこれから再生される音声の格納番号を抜き出して判定用変数に格納
	if( array_ch[arg_voice01].position > 0 ){ //再生ヘッドをチェック(もし再生ヘッドが0より大きければ…つまり再生していれば)
		trace( "再生中だったので停止してイベント開放" );
		fnc_stopsound(); //停止処理を実行
		array_ch[my_evesound].removeEventListener(Event.SOUND_COMPLETE, fnc_soundcomp); //音声再生完了イベントを開放
	} else {
		trace( "再生中ではない" );
		fnc_stopsound(); //既に再生中の別の音声があった時のために停止処理を実行
		array_ch[arg_voice01] = array_sound[arg_voice01].play(); //引数に入っている数字を使い音声を再生
		array_ch[arg_voice01].addEventListener(Event.SOUND_COMPLETE, fnc_soundcomp); //音声再生完了イベントを登録
	}
}

/*
停止メソッド
*/
function fnc_stopsound():void{
	for( var i:int = 0; i < my_XML.sound.voice.length(); i++){ //xmlのノードから総数を取得してその回数実行
		array_ch[i].stop(); //まず停止
		array_ch[i] = array_sound[i].play( 0 ); //再生ヘッドを0に戻す
		array_ch[i].stop(); //戻して即時停止で0のままに
	}
}

/*
サウンドコンプリートハンドラ
*/
function fnc_soundcomp(e):void{ //再生完了まで別のボタンが押されなかった時のために再生ヘッドを元に戻すのに使う
	trace( "再生完了したので停止してイベント開放" );
	fnc_stopsound(); //停止処理を実行(停止処理には再生ヘッドを0に戻す処理も含まれる)
	array_ch[my_evesound].removeEventListener(Event.SOUND_COMPLETE, fnc_soundcomp); //音声再生完了イベントを開放
}

キモは"一回は再生しないとstop()メソッドでエラーが出る"ことと、"再生完了イベントを使い、再生ヘッドを0に戻す"ことの2つです。

複数ボタンがある場合、順番に押されてしまった時に重複して再生させないために、停止処理を作成しておきます(fnc_stopsoundという名前にしました)。そして、順番ではなく、同じボタンが押された時に音声が停止するのが自然だと思ったので現在再生中の音声と再生ボタンで呼び出される音声が一致して、かつその音声が再生中なら停止させる…という処理にしました。判定にはsoundchannelのプロパティpositionを使いました(positionは音声の現在の再生位置、つまり再生ヘッドを数字で返してくれます)。

単純にボタンだけの処理で終わらせてしまうと、"音声が自然に最後まで行って停止したとき"に不具合が起きます。as3の音声再生は音声が再生し終わっても再生ヘッドを0に戻してはくれないからです(テープのようなものです)。

ですので、音声再生と同時に再生した音声のsoundChannelにコンプリートイベントを発生させて、"音声が自然に最後まで行って停止したときに再生ヘッドを0に戻す"処理も記述しておきます。

以上で複数の音声を再生するボタンの作成は終了です。

この一連のやりかたを使えばゲームサイトやアニメ公式サイトのキャラクター紹介のサンプルボイスを再生するflashなどが簡単につくれるでしょう。ぜひご活用ください。そしてご活用いただけたらぜひ教えてください。

この記事で使っている音声はVoicePro様のフリー音源を活用させていただきました。ありがとうございました。

使用音源:VoicePro様

カテゴリー: WEB DESIGN | コメントは受け付けていません。

[as3]FLASH(actionscript3)で音声を鳴らしてみよう

as3でmp3ファイルなどの音声データを再生するシーンって結構あると思います。

例えば著名人の公式サイトで「~さんのボイスメッセージ」とか、アニメやゲームの公式サイトでキャラクター紹介に「CV:田中太郎 [SAMPLEVOICE]」とかボタンを設けてクリックすると再生とか。

単純に特定のイベント時に再生すればいいだけなら以下のような感じです。

var sound_obj:Sound = new Sound( new URLRequest( "ファイルへのパス" ) ); //サウンドオブジェクトを作ってURLから音声データを呼び出し
var sound_ch:SoundChannel; //停止などに使うサウンドチャンネルオブジェクトを作成

sound_ch = sound_obj.play(); //再生したいタイミングで実行

sound_ch.stop(); //停止したいタイミングで実行(但し一回は再生していないとエラーが出ます)

as3のサウンド処理は2つのオブジェクトがそれぞれ分担作業を以下のような感じでしています

Soundオブジェクト
請求された音声を格納する役割
音声を再生する役割
SoundChannelオブジェクト
音声を停止する役割
ボリュームを制御する役割(右/左)
一時停止に使う再生ヘッドを取得する役割
再生終了のお知らせを出す役割

他にも細々あるんですが、まあ概ねこのような感じです。

音声関連でややこしくも重要なルールは2つ。

  1. 「Soundは再生だけ、停止はSoundChannel」
  2. 「音声を停止させるstop()メソッドは最低1回はplay()メソッドが走っていないとエラーが出る」

これで音声の基本は終わりです(たぶん)。

次回投稿では複数の音声再生ボタンを作り、それぞれに違う音声を割り当ててみます。

カテゴリー: FLASH | コメントは受け付けていません。

[LIFE]PCのメモリ増設について

サブPCがアプリケーション増やしたらなんかカクカク感じるようになってきたのでメモリを増設してみる事にしたんですが、DDRだとかなんだとかあったはずなので買う前に調べてみました。

でもどのサイトもなんかムニャムニャ難しい事ばっかりで「わけがわからないよ/人◕‿‿◕人\」状態になりそうでしたが、とりあえず2つだけ気をつければいいみたい。

種類
SDRAM、DRDRAM、DDR、DDR2、DDR3、DDR4の6種類。
FSB(メモリーバス)
マザーボードによりまちまち。

まず大きく6種類の中から選んで、あとはマザーボードが対応した周波数であればいい、ということみたいですね。

PC開けてメモリを見ればだいたいラベルがくっついてますが、それでわからなければVectorとかでFSBを調べるツールを落とせばいいかしら。

カテゴリー: LIFE | コメントは受け付けていません。

[LIFE]スカイリムから

現実に帰る時間がなかなかとれない

カテゴリー: WEB DESIGN | コメントは受け付けていません。

[as3]flashからfancyboxを起動

jQueryプラグインの「fancybox」。

画像やhtmlページをポップアップさせるプラグインとしては動作も軽快でオプションも豊富、設定もわかりやすくて最高のjQueryプラグインです。

そんなfancyboxをflash側(actionscript3)から起動して、ついでに起動するリンクを簡単に変更できるように外部xml管理にしてみます。

【1】ライブラリを入手する

jQueryのプラグインなのでまずはjQuery本体を入手。(※fancyboxに格納されている場合もあります/2011年11月現在)

http://jquery.com/

次にfancyboxを入手。

http://fancybox.net/

続けてflashの表示を助けるswfobjectを入手

http://code.google.com/p/swfobject/(※バージョンは”swfobject_2_2.zip”を推奨)

一式入手したら以下のような構成でフォルダに格納します。

【2】flaファイルを作ってボタンを設置

新規flaファイルを作ってボタンシンボルをステージ上に設置します。

レイヤー構造はボタンとas(actionscript)だけです(一個にまとめてもいいですが)。

設置したボタンにはasから操作できるようにインスタンス名を付けましょう。

【3】xmlを作成&記述

とりあえず1個しかボタンがないので子ノードを1個つくってリンクを記述。シンプルです。


<banner>

	<mysite url="http://wrelish.com/shared/images/index_mainvis.png">WithRelish</mysite>

</banner>

うちのブログのタイトル画像を指定してみました。

【4】flaファイルに戻ってxmlをロード
var my_xml_loader:URLLoader = new URLLoader();
var my_XML:XML;
var my_fancyurl:String; //この変数にURLを格納する

my_xml_loader.load( new URLRequest("banner.xml") );
my_xml_loader.addEventListener(Event.COMPLETE, fnc_xml);

function fnc_xml(e):void{

	XML.ignoreWhitespace = true;
	my_XML = new XML(my_xml_loader.data);

}

これで”my_XML”に【3】のxmlが入りました。

【5】fancyboxを起動するためのスクリプトを記述

XMLをパースしてURLを取り出したら、fancyboxを起動するための記述に合体させます

my_fancyurl = "javascript:fnc_connect( '" + my_XML.mysite.@url + "' )";

これは【4】のfnc_xmlって関数の中に書いてください。

そしてクリックイベントを登録。

ins_btn.addEventListener(MouseEvent.CLICK, fnc_gotourl);
function fnc_gotourl(event:MouseEvent):void {
	navigateToURL( new URLRequest( my_fancyurl ), "_self" );
}

これでflash側は終了。”swf_fancybox.swf”って名前でパブリッシュして【1】の構成でフォルダへ。

ちなみにfancyboxを起動するための記述の中身の説明はこんなかんじ

【6】html側にリソースを読み込み

まずはflashを表示する記述から


<!--flash_js-->
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript">
	swfobject.embedSWF("swf_fancybox.swf","test_banner","300px","300px","10.0.0",'expressInstall.swf',{},{wmode: "transparent"},{});
</script>
<!--/flash_js-->

まず”swfobject.js”を呼び出して、次にオプションで呼び出したいswfとかを決める

次にswfを表示したい位置(body内)に”test_banner”というIDの付いたタグを記述


<p id="test_banner"></p>

次にjQuery系


<!--jQuery-->
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>

	<!--fancybox_imagepopup_option-->
	<script type="text/javascript" src="jquery.fancybox-1.3.1.js"></script>
	<link rel="stylesheet" type="text/css" media="screen" href="jquery.fancybox-1.3.1.css" />
	<!--/fancybox_imagepopup_option-->

<!--/jQuery-->

これで準備は完了です。

【7】flashから実行するための関数を記述

【5】で実行先として記述した関数”fnc_connect”を作ります。


<script type="text/javascript">
	function fnc_connect(url){
		var fancylinks = document.createElement('a'); //<a>を作成
		fancylinks.setAttribute('href',url); //<a>に属性"href"と値"url"を追加。urlはflash側から来ている値を格納した変数なので"javascript:fnc_connect( 'xmlから取得したリンクURL' )"が入る
		fancylinks.setAttribute('title',"swfからfancyboxをキック"); //<a>に属性titleと値を追加。値は「""」で囲むことでそのまま文字列が出力される
		$(fancylinks).fancybox({ //作成した<a>タグに対してfancybox関数をキック
			'overlayOpacity' : '0.5', //画面を覆うオーバーレイの透明度0.1~1の間で設定
			'overlayColor' : "#333333", //オーバーレイの色
			'transitionIn'		: 'easeInOutBack', //表示時のエフェクト
			'transitionOut'		: 'easeInOutBack', //消去時のエフェクト
			'autoScale'			: false, //表示対象にあわせてサイズを自動調整するか(trueならする、falseならしない)
			'type'				: 'iframe', //表示モード(
			'width'				: 600, //表示の横幅
			'height'			: 338 //表示の縦幅(でもってこれが最後のオプションなので「,」は付けない
		});
		$(fancylinks).trigger('click'); //ここで始めてfancyboxのイベントを実行(ポップアップを表示)します。
	}
</script>

これで全て完了。

【EX1】actionscriptの最終コード
var my_xml_loader:URLLoader = new URLLoader();
var my_XML:XML;
var my_fancyurl:String;

my_xml_loader.load( new URLRequest("banner.xml") );
my_xml_loader.addEventListener(Event.COMPLETE, fnc_xml);

function fnc_xml(e):void{

	XML.ignoreWhitespace = true;
	my_XML = new XML(my_xml_loader.data);

	my_fancyurl = "javascript:fnc_connect( '" + my_XML.mysite.@url + "' )";
}

ins_btn.addEventListener(MouseEvent.CLICK, fnc_gotourl);
function fnc_gotourl(event:MouseEvent):void {
	navigateToURL( new URLRequest( my_fancyurl ), "_self" );
}
【EX2】htmlの最終コード

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<meta http-equiv="content-language" content="ja" />

	<!--flash_js-->
	<script type="text/javascript" src="swfobject.js"></script>
	<script type="text/javascript">
		swfobject.embedSWF("swf_fancybox.swf","test_banner","300px","300px","10.0.0",'expressInstall.swf',{},{wmode: "transparent"},{});
	</script>
	<!--/flash_js-->

	<!--jQuery-->
	<script type="text/javascript" src="jquery-1.4.2.min.js"></script>

		<!--fancybox_imagepopup_option-->
		<script type="text/javascript" src="jquery.fancybox-1.3.1.js"></script>
		<link rel="stylesheet" type="text/css" media="screen" href="jquery.fancybox-1.3.1.css" />
		<script type="text/javascript">
			function fnc_connect(url){
				var fancylinks = document.createElement('a');
				fancylinks.setAttribute('href',url);
				fancylinks.setAttribute('title',"swfからfancyboxをキック");
				$(fancylinks).fancybox({
					'overlayOpacity' : '0.5',
					'overlayColor' : "#333333",
					'transitionIn'		: 'easeInOutBack',
					'transitionOut'		: 'easeInOutBack',
					'autoScale'			: false,
					'type'				: 'iframe',
					'width'				: 600,
					'height'			: 338
				});
				$(fancylinks).trigger('click');
			}
		</script>
		<!--/fancybox_imagepopup_option-->

	<!--/jQuery-->

</head>
<body>

<p id="test_banner"></p>

</body>
</html>

これで完了です。あ、そうそう、通信をするのでローカルで実験したい方はグローバルセキュリティ設定をしておかないと実行できません。お気をつけください

この記事は以下参考文献「懐古宴」様のas2のサンプルを参考にしました。

参考文献:http://kaikoen.ne4.org/?p=106

カテゴリー: FLASH | タグ: , | コメントは受け付けていません。