Twitterやってます。
2010.09.10

感想と推薦

UNISON SQUARE GARDEN - UNISON SQUARE GARDEN

THE BACK HORN、GRAPEVINEを聞いていたと言うだけあって、そのテイストが感じられる曲調。3ピースでも音にしっかりとした厚みがあって、バランスが良いと思った。

just A moment - 凛として時雨

その名の通り、切なくて冷たい雨が降る。TK(男性Vo)のハイトーンは好みが分かれるところだが、345(女性Vo)とのツインボーカルが生み出す緊迫感はとても狂おしく、破滅的で情緒に溢れている。

軌道-WARPHOLL

でもね、曲はめっちゃカッコイイス。そういう細かいところを気にするアホウは僕くらいなもんで、良いアルバムに仕上がってますよ。

衝撃の展開に思わず笑みがこぼれる一品 "Stick Stickly" Attack Attack!

いやはや、凄いの見てもーた。基本はスクリーモなんですが、エモが来たと思ったらいきなりエレクトロニカなん?4つ打ちなん?っていう最高の一品です。

On Fire-The Higher

1曲目の「insurance?」からいきなり「It's Only Natural」と似たテイストのノリノリナンバーで、一気に持ってかれてしまいました。全体的に気持ちよく聴けるアルバムに仕上がっています。

SO MANY MUSIC,SO MANY COLORS - Looking For

埼玉産インディーズバンドLooking For。同郷なら応援しないわけにはいかない。とにかくメロディック・メロディックなのであります。まさしく僕好み。ありがとうございます。

NIGHT FISHING - サカナクション

初めて聴いた感想はズバリ「つまらん」。 で、封印しようかと思いつつ、他に聴くものもないし・・・などとループ再生していたところ・・・4,5回目くらいから良くなってきました。

Music is the key-UNCHAIN

僕のファーストインプレッションは、 「んー、フライングキッズ?いや、オリジナルラヴ?」 でした。 前作 rapture が割とアップテンポで勢いのある印象だったので、アップテンポ好きな僕には少し物足りないというか、お子ちゃまな僕の好きな路線とはちょっと違うかなぁという感想。

air feel,color swim - school food punishment

女性Vo.なんですが、彼女の声と曲の世界観が絶妙です。彼女の声を聴いていると、切なくなるような、苦しくなるような、かと思えば一気に解放されるような、フワフワ浮かんでいるような。 クラムボンが好きな人とかすんなり聴けるんじゃないかと思います。

ALBO─Mistral

正統派J-popとでもいうべき非常に聴きやすい作品。メロディーも心地よく耳に残る感じ。無意識のうちに結構気に入っていたらしく、このまえ気付いたら4曲目のサビをひたすら口ずさんでました。
RSS
2009.05.31

Thread(そうめん)とTweenerで作るスライドショーFLASH

ずっと気になっていたライブラリのひとつにActionScript Thread Library 1.0 (そうめん)があったのですが、「AS3初級者がこんな凄そうなの触ったら速攻爆死確定ジャマイカ」という予感の元、タイミングを窺っておりました。

そんな時に知人から、「そうめんよかProgression超便利っすよ!みたいな?」なんて言われちゃったもんだから、なんだか素直に従うのも癪なので、爆死覚悟でそうめん喰ってみます。

全ての始まりはここから。

ActionScript Thread Library 1.0 (そうめん) ドキュメント

凄く丁寧に書かれているので、これを読めば良いのですが、僕の場合、全部の書かれている意味をそれなりに理解するのに半日、4回は読み直しました。。。ナハナハ

あと、ソースに同梱されているサンプルが非常に役に立ちます。僕の場合、コピペしまくりでした。。。ナハナハ

スライドショーFLASHの仕様

今回作るFLASHの仕様を決めるます。

そもそもなんでスライドショーなのかというと、仕事でなぜかよく

「ここの写真、スライドショーのが良くね?※1」

なんて話になり、そんなときは

「オーケーJohnny,そういうのにぴったりのモノがあるんだぜ!※2」

なんつって、昔作った「俺様謹製AS2版スライドする的なFLASH」を使ってきたわけですが、そろそろAS3版もあっても良かろうかと言うことで、今回そのベースとなるものをそうめんで作ってみることにしました。

※1 ビジネスの現場ですので実際は丁寧な日本語が使われています。たぶん。
※2 Johnnyは仮名です。大抵のJohnnyは日本人です。

話がそれました。
こんな仕様のFLASHにします。

XMLファイルの読み込み(画像のアドレスとリンク先が記述されている)

一枚目の画像を読み込む


 ●Tweenerでフェードイン
 ■次に表示する画像の読み込み開始、読み込み完了後ステージに透明な状態で配置

●と■の両方が終わったら★に戻る

うーん。この書き方で分かるだろうか。要するに、画像を表示している裏で次に表示する画像の読み込みを行うという並列処理をそうめナイズしたいわけです。

クラスファイルの構成はこうしました。

App.as :ドキュメントクラス
MainThread.as :スレッドの親玉
 ├ Fade.as :Tweenerでフェードインする
 └ ImgLoad.as :画像を読み込む

ドキュメントクラスでそうめんの初期化

さっそく書いてみます。まずはドキュメントクラスでそうめんを初期化だそうです。
ここはもうコピペです。はい。

ドキュメントクラス:App.as

package  
{
	import flash.display.Sprite;
	import org.libspark.thread.Thread;
	import org.libspark.thread.EnterFrameThreadExecutor;
	
	public class App extends Sprite
	{
		public function App() 
		{
			//Threadのイニシャライズ
			Thread.initialize(new EnterFrameThreadExecutor());
			//MainThread開始
			var main:MainThread = new MainThread(this);
			main.start();
		}
	}
}

一連の動作を制御するスレッドの親玉を作る

 本家のドキュメントに従い、extends Threadしたクラスを作成します。
override protected function run()から始まるのが作法みたいです。
overrideなんてやったことないので、早速泥沼化必至です。でも見よう見まねで進めます。今までもそうやって生きてきたし。

MainThread.as

package  
{
	import flash.display.DisplayObjectContainer;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.errors.IOError;
	import org.libspark.thread.Thread;
	import org.libspark.thread.threads.net.URLLoaderThread;
	import org.libspark.thread.utils.Executor;
	import org.libspark.thread.utils.ParallelExecutor;
	
	public class MainThread extends Thread
	{
		/**
		 * コンストラクタ
		 */
		public function MainThread(container:DisplayObjectContainer)
		{
			_container = container;
		}
		
		private var _container:DisplayObjectContainer;
		private var _xmlUrl:String = "slideShow.xml";
		private var _xmlLoader:URLLoaderThread;
		private var _xmlData:XMLList;
		private var _counter:int = 0;
		private var _linkUrl:String;
		
		/**
		 * XMLの取得
		 */
		override protected function run():void
		{
			//XML読み込み定義(URLLoaderThread)
			_xmlLoader = new URLLoaderThread(new URLRequest(_xmlUrl));
			//XML読み込み開始
			_xmlLoader.start();
			//XML読み込み完了まで待つ
			_xmlLoader.join();
			//XML読み込み完了後の指示
			next(xmlLoadComp);
			//エラーの時
			error(IOError, errorHandler);
			error(SecurityError, errorHandler);
		}
		/**
		 * XML読み込み完了
		 */
		private function xmlLoadComp():void
		{
			//読み込んだXMLを格納
			var myXML:XML = new XML(_xmlLoader.loader.data);
			_xmlData = myXML.item;
			//一個目の画像を読み込む
			var firstImg:ImgLoad = new ImgLoad(_xmlData[0].photo[0], _xmlData[0].link[0], _container);
			firstImg.start();
			firstImg.join();
			_counter++;
			next(sequence);
		}
		/**
		 * 次の画像の読み込みと、フェードインの2つの動作をParallelExecutorで監視
		 */
		private function sequence()
		{
			//ParallelExecutorを用意
			var paraExec:ParallelExecutor = new ParallelExecutor();
			//ParallelExecutorに画像の読み込みとフェードインスレッドを追加
			paraExec.addThread(new Fade(_container));
			paraExec.addThread(new ImgLoad(_xmlData[_counter].photo[0], _xmlData[_counter].link[0], _container));
			//カウンタを1増やす
			if (_counter < _xmlData.length() - 1) {
				_counter++;
			} else {
				_counter = 0;
			}
			//スレッドスタート
			paraExec.start();
			//完了待ち
			paraExec.join();
			//次へ
			next(sequence);
		}
		/**
		 * エラー処理
		 */
		private function errorHandler(event:IOError, t:Thread):void
		{
			trace("エラー:" + event.getStackTrace());
			next(null);
		}
	}
	
}

 しっかしもっと短く書けないのかな。きっともっと効率的なやり方があるに違いない。
まぁ、それはともかく、ポイントはParallelExecutorです。並列処理の部分をこのParallelExecutorが監視してくれます。ParallelExecutorに●フェードインスレッドと■次の画像読み込みスレッドをaddThreadすることで、両方が完了するまで処理を止めることが出来ます。

これは結構便利なんじゃないかと思います。複数のファイルをバーッと読み込みたいときはいいかも。
あと、XMLの読み込みにURLLoaderThreadを使用。これは読み込み完了を待ってくれるURLLoaderみたい。

で、セットしたスレッドはstart()で開始して、join()すれば待機モードになる。next(func)で完了時の次の動作だわな。

画像の読み込み部分をLoaderThreadで作る

画像を読み込む部分のクラスです。
LoaderThreadを使うのですが、これはURLLoaderThreadがURLLoaderクラスを使用しているのに対し、Loaderクラスを使用してファイルを読み込むという違いがあります。

んで、URLLoaderとLoaderの違いって何よ?っていったらあなた、僕が分かるわけないじゃない!(逆ギレですね?わかります。)

よく分からないので、XMLはURLLoader、画像類はLoaderと覚えてます。だって巷のサンプルソースがみんなそうなんだもの。ナハナハ

ImgLoad.as

package  
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;
	import flash.errors.IOError;
	import org.libspark.thread.Thread;
	import org.libspark.thread.threads.display.LoaderThread;
	
	public class ImgLoad extends Thread
	{
		
		public function ImgLoad(url:String, linkUrl:String, container:DisplayObjectContainer)
		{
			_url = url;
			_linkUrl = linkUrl;
			_container = container;
		}
		
		private var _url:String;
		private var _linkUrl:String;
		private var _imgLoader:LoaderThread;
		private var _container:DisplayObjectContainer;
		private var _photo:Sprite;
		
		/**
		 * 画像読み込み
		 */
		override protected function run():void
		{
			//読み込み定義(loaderThread)
			_imgLoader = new LoaderThread(new URLRequest(_url));
			//読み込み開始
			_imgLoader.start();
			_imgLoader.join();
			//読み込み終わったら
			next(imgSet);
			//エラーの時
			error(IOError, errorHandler);
		}
		/**
		 * スプライトを作ってその中に画像を入れ、透明にしてステージに配置
		 */
		private function imgSet():void
		{
			_photo = new Sprite();
			_photo.visible = false;
			_photo.alpha = 0;
			_photo.buttonMode = true;
			_photo.addChild(_imgLoader.loader.content);
			_container.addChild(_photo);
			//クリックセット
			_photo.addEventListener(MouseEvent.CLICK, imgClick);
		}
		/**
		 * クリックされたときの動作
		 */
		private function imgClick(event:MouseEvent):void
		{
			navigateToURL(new URLRequest(_linkUrl));
		}
		/**
		 * エラー処理
		 */
		private function errorHandler(event:IOError, t:Thread):void
		{
			trace("エラー:" + event.getStackTrace());
			next(null);
		}
	}
}

そもそもこの仕様で作っちゃったのが癌なのかもしれないけれど、このクラスでクリック時の動作を定義していて、このイベントをイベントリスナーじゃなくスレッドでevent()ってやったら最後、スライドショーがスライドしません。。。ナハナハ

そりゃそうだよね、親が「終わるまで待ってるよ」って言ってるのに、子供がクリック待ちしてたら次にいけないよね。本当はイベントリスナーを使わないで完成させたかった(意味ないけど)んだけど、変な拘りはやめました。
ということで、ごく普通のクリック設定です。

フェードイン部分をTweenerThreadで作る

画像がフェードインする部分のクラスです。
TweenerThreadってまんまTweenerなんだけど、予想外にスペシャルプロパティshow:trueが役に立った。これはTween開始時にvisibleをtrueにしてから動作するというもので、こういう痒いところに手が届いている点は開発者様の愛を感じます(笑)。

ただ、こうやって作ってみて思うのは、「TweenerのonCompleteでいいんじゃね?」ということ。
これは恐らく使いどころを間違えてますね。アタクシ。でもいいんです。これもまた勉強。頑張れ俺。

Fade.as

package  
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import org.libspark.thread.Thread;
	import org.libspark.thread.threads.tweener.TweenerThread;
	
	public class Fade extends Thread
	{
		public function Fade(container)
		{
			_contianer = container;
		}
		private var _contianer:DisplayObjectContainer;
		/**
		 * 画像のフェードイン
		 */
		override protected function run():void
		{
			var target:DisplayObject = _contianer.getChildAt(_contianer.numChildren -1);
			//TweenerThread定義
			var tween:Thread = new TweenerThread(target, {
				alpha:1,
				time:2,
				show:true
			});
			tween.start();
			tween.join();
			next(waiting);
		}
		/**
		 * 待機
		 */
		private function waiting():void
		{
			sleep(1 * 1000);
			next(lowerImgRemove);
		}
		/**
		 * 下の画像を消す
		 */
		private function lowerImgRemove():void
		{
			if (_contianer.numChildren > 2)
			{
				_contianer.removeChildAt(0);
			}
		}
	}
}

やっと完成です。

まさかこんなに長くなるとは思わなかった。ファイルも2個の想定が4個だし。でも非常に勉強になりました。
そうめんを知らなくても、使わなくても、恐らく今後困ることは無いのだろうけど、こうやって別のやり方があることを知ったことで知識の引き出しが増えて、いつか役に立つときが来るかも。なんて思うと感無量であります。

ということで、完成版はこちら

XMLはこちら

トラックバック(0)

トラックバックURL:

コメント(2)

そうめんの使いどころ、とても参考になりました。
各クラス構成もよくまとまっていて勉強になります。
スライドショーはFlashの基本とも言えますが以外と奥が深く、どう実装するか毎回迷うところです。
この記事は多くの人の為になると思います。

はじめまして。
最近ASの勉強をしている者です。
他のサイトのスライドショーのサンプルを見ましたが、こちらのスライドショーはシンプル・イズ・ベスト!ですね♪

私もスライドショーを作りたく、こちらの記事を参考にさせて頂きました。しかし、どうもうまく動きません(汗)

宜しければ、データで頂ける事は可能でしょうか?

コメントする

お名前 Eメイル
URL ログイン情報を記憶