一定の時間間隔で何かの関数を繰り返し実行したいというケースでは
JavaScriptのタイマー関数が利用されます。
JavaScriptのタイマー機能について
例えば「id=setTimeout("実行文",時間)」で指定時間後に特定の動作をさせられます。
「clearTimeout(id)」で設定したタイマーをクリアします。
無限回実行では「id=setInterval("実行文",時間)」が使え
「clearInterval(id)」で停止します。
setTimeout(),clearTimeout()の問題点
先のタイマー関数には使いにくい面があります。
上記関数に渡す引き数は "実行文"の文字列か関数オブジェクトになるため
「eval("実行文")」の場合と同じくそれらの中で参照する変数は
大域的に定義されている必要があります。
これは変数「s」がローカルであるためエラーになります。
IE6:エラー:'s'は宣言されていません。 Netscape4:s is not defined.
このコードを通すには 「s」をグローバルにする必要があります。
しかしこの方法はすぐに危険だと分かります。関数f()を異なる場所で複数回
呼び出す場合、大域変数「s_global」を上書きしてしまう可能性があるからです。
上の例のように「f("Hello!");」を実行後、直ぐに「f("GoodBye!");」を実行したら
「Hello!」が表示されるはずの1秒後に「GoodBye!」が表示されます。
呼び出す関数の引き数が沢山ある場合、任意回数の呼び出しがある場合に
ちょっと面倒になります。
そこで タイマー機能を簡単に実行できる関数を考案しました。
以下の特徴があります。
kl_timer_new/start/stop()の特徴
|
タイマー実行中でも 登録した関数内&外部コード から現在のタイマーの状態を
参照&変更できる。 (New!)
登録関数内からは「this」の「kl_...」属性として、外部からは
「kl_timer_start/new()」の返り値Objectの属性として利用できます。
this.kl_cnt:現在のカウント値(0〜reps-1)、
this.kl_reps:回数(-1〜)、
this.kl_func:関数、
this.kl_args:引き数配列、
this.kl_msec:実行間隔、
this.kl_onstart:開始時に実行する文字列(or 関数 or 関数と引き数の配列)
this.kl_onstop:停止時に実行(同左)
などなど下記コード参照。
|
|
関数オブジェクトを渡す場合、引き数も指定できる。
引き数をグローバル変数にとっておく必要がないので便利 |
|
タイマー実行中に退避しておきたオブジェクトができたら
thisの属性として保持できる。 (New!)
this.MyObj=...とできます。グローバル変数に置かなくて済むのでコードが簡略明快に! |
|
回数指定ができる。
省略・負数指定時は無限回実行
|
【タイマーの利用:kl_timer_start/stop()<keynavi_tools.js】
-----------------------------------------------------------------------------
■ kl_timer_start/new(func,[args],msec,reps,use_settimeout,pass_cnt,pass_obj)
・返り値:タイマー機能に必要な情報を格納したオブジェクトv(コード参照)
・func:呼び出す関数か処理内容を記述した文字列
返り値としてfalseが返されるとタイマーの実行が停止します。
・args:関数の引き数配列 (略可)
・msec:呼び出し間隔 (msec単位)
・reps:呼び出し回数(-1 or 省略されたら無限回) (略可)
・use_settimeout:全ての処理が終ってから次の処理までのタイマーを設定する場合真
・pass_cnt:関数の第1引き数に現時点での呼び出し回数を渡す
・pass_obj:関数の第1引き数にオブジェクトvを渡す(コード参照)
■ kl_timer_stop(v):設定されたタイマーをクリアする(=停止する)
■ kl_timer_restart(v):停止したタイマーを再開する
・v:kl_timer_start/new()の返り値
-----------------------------------------------------------------------------
。。。(略)。。。
kl_timer_...()の利用例
この関数を利用すると 先の例は以下のようになります。
この場合は 2つの実行文がきちんと別々に実行されることが分かります。
Window属性の関数
上の例では「alert(s)」を直接実行せず 関数「g(s)」で被せています。
WinIEでは「kl_timer_start(alert,...)」とできますが一部ブラウザで不可です。
window属性の関数 alert()やclose()は 別のObjectに代入後に実行すると
エラーになる為です。このように別の関数で被せれば万事OKです。
「g(s)」無しに一行で書いてしまいたい場合は
「kl_timer_start(new Function("s","alert(s)"),new Array(s),msec,1)」
とできます (互換性OK)。
ユーザが定義した一般の関数を登録する時や
関数ではなく実行文字列を指定する場合はこのような配慮は不要です。
定番の現在時刻の表示。ステータスバーに現在の時刻を表示します。
このように setInterval()のようにも書けます。
次の例では実行カウントを1秒ごとに3回表示します。
「0」「1」「2」が順に表示されます。
自分でカウンタを作らなくても登録関数内から「this...」で
現在のタイマー状態にアクセスできます。
レイヤーの制御に使ってみましょう。
この例では半透明のレイヤーが右下方向に(1px,1px)ずつ移動していきます。
次は文字列を順番に表示させて見ます。
複数のレイヤーが重なってしまったらドラッグして移動できます。
上の例では タイマー情報を記憶している
オブジェクト「this」にアクセスしています。
文字列を格納するのに大域的な変数を用いず 「this.neko」においています。
こうすると別のタイミングで「soseki("red")」が呼ばれても
変数が混じらないためそれぞれが独立してきちんと動作します。
複数のタイマーを使うケースでは状態変数の置き場所に困るケースが多いのですが
「this」に置けるので重宝します。