しつこく文字列横スクロールの話。
前回までは1つの文字列を一度スクロールさせたら終わりだったが、今回は複数の文字列(配列にセット)を順番に延々とスクロールさせ続けるプログラム。
一回で終わりなら timerComplete イベントで終了処理(文字列が左端に消えていく処理)を行えばいいのだが、複数の文字列の表示を順に延々行うケースで timerComplete イベントは使えない。だって、「延々処理を繰り返す」ので TIMER_COMPLETE な状態にはならないもん。
ということで、グローバル変数でスクロール処理回数を保持し、それと文字列の表示枠の大きさとを比較して処理の終了タイミングを見たり、次の文字列に移ったとき、スクロール処理回数を初期化(0回)したりといった「泥臭い」処理を組み込んでやる。これが一番簡単。下手に複数の Timer イベントを駆使して実現しようとすると地獄を見るし、技術者的には楽しいかもしれんけど、そんなソースを後で見せられてもメンテナンスできんで。(笑)
ということで、以下がサンプル。
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
initialize="initProc();" width="367" height="109">
<mx:Script>
<![CDATA[
// グローバル変数
public var TextIndex:int; // 処理中の文字列配列添字
public var ProcCount:int; // 処理の実行回数
public var TextData:Array = new Array(); // 表示文字列
public var TextLastData:Array = new Array(); // 消えていく文字列処理用
// 定数
// text1 に表示できる最大文字数
public static const MAX_TEXT_SIZE:int = 40;
//================================================================
// 初期処理(メイン)
//================================================================
private function initProc():void {
setText(); // 表示文字列を配列にセット
TextIndex = 0; // 最初の配列
ProcCount = 0; // 文字列セット処理回数 0回
// ひたすら表示文字列セット処理を呼び続ける
var timeCheck1:Timer = new Timer(100); // 100ミリ秒毎
timeCheck1.addEventListener(TimerEvent.TIMER, setText2Label);
timeCheck1.start();
}
//================================================================
// ラベルへの表示文字列セット処理
//================================================================
private function setText2Label(event:TimerEvent):void {
ProcCount++;
if (ProcCount <= 1) { // 初回のみ
TextLastData[TextIndex] = TextData[TextIndex];
}
// まだ、処理回数が文字列の長さを超えてない?
// (ちなみに、文字列が左端まで行ったところで 2秒ほど動きを
// 停止させたいので MAX_TEXT_SIZE に +20している)
if (ProcCount <= (MAX_TEXT_SIZE + 20)) {
// 時間が経過する毎に、表示文字列の前に挿入する全角スペー
// スの数を減らしていく
var blankCnt:int = MAX_TEXT_SIZE - ProcCount;
if (blankCnt <= 0) {
label1.text = TextData[TextIndex];
}
else {
label1.text = (new Array(blankCnt).join(" ")) + TextData[TextIndex];
}
}
else {
// 時間が経過する毎に、表示文字列の一番前の文字を削除
// (文字列がだんだん消えていく動き)
TextLastData[TextIndex] = TextLastData[TextIndex].substr(2);
label1.text = TextLastData[TextIndex];
// 最後に、次の文字列処理を許可する
if (TextLastData[TextIndex] == '') {
TextIndex++;
ProcCount = 0; // 処理回数初期化
// 配列の最後までいったら最初に戻る
if (TextIndex >= TextData.length) {
TextIndex = 0;
}
}
}
}
//================================================================
// 表示文字列の設定
//================================================================
private function setText():void {
TextData[0] = "わたしは宇宙からきたゴリ星人だ。";
TextData[1] = "あなたは衣笠似のゴリラだ。";
TextData[2] = "あなたはゴリラ似のガッツ石松だったのですね?";
}
]]>
</mx:Script>
<mx:Label x="41" y="24" text="この下に文字が流れながら表示されます"/>
<mx:Label x="41" y="50" width="279" id="label1"/>
</mx:WindowedApplication>
ちなみに、TextIndex が 0 のときに setText 処理を呼ぶようにすれば、TextLastData を使わずに直接 TextData を使えばいいので、グローバル変数も減るし、TextData の値を TextLastData にセットする処理も減るので幾分ソースもスッキリすると思うが、そこは、まあ、好き好きで。