このフォーラムで、シーク機能について質問が投げられていたので作ってみた。
Flex2でFLVプレイヤーを作ろうと思ったら、ボタンなどの標準コンポーネントを使って 簡単に実装できちゃうんですが、シークバーはちょっとポイントが要ります。 でもだからといって、コンポーネントを作らないといけないわけじゃなくて、 HSliderとスクリプトだけでなんとかできちゃいます。

こんな感じになる。それっぽいでしょ?
コントローラを配置
まずはFLVを表示するためのVideoDisplayクラスと シークするためのHSliderクラスを準備
- <?xml version="1.0" encoding="utf-8"?>
- <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
- <mx:VBox width="100%" height="100%">
- <mx:VideoDisplay id="myVD" width="100%" height="100%" source="your.flv" />
- <mx:HSlider id="myHS" width="100%" />
- </mx:VBox>
- </mx:Application>
FLVの再生位置とシークバーを同期させる
これだけでもFLVは再生されるので、再生されている位置とシークバーを同期させてみます。
ここからは基本的に編集するのはHSliderのみ
- <mx:HSlider id="myHS"
- width="100%"
- minimum="0"
- maximum="{myVD.totalTime}"
- value="{myVD.playheadTime}"
- />
スライダーの最小値と最大値を決定します。 最大値にビデオの総時間をバインディングされるようにしておき さらにビデオの再生位置に変更があるたびに、スライダーの値とビデオの再生時間が同期するように仕込む。 これで、再生時間 / 総再生時間みたいなことを気にしないでも、スライダーが勝手に計算してくれます。
スライダーからの変更をビデオに反映する
次にスライダーからビデオの再生位置を変更できるようにします。 HSliderに次の行を追加します。
- change="{ if(myVD.stateResponsive) myVD.playheadTime = myHS.value }"
VideoDisplay#stateResponsiveはビデオが応答可能かどうかの判定メソッドです。 まだ動画がロードされていなかったり、ビジーな状況を回避しつつ スライダーのvalueをそのままビデオの再生位置時間に代入します。 これはスライダーとビデオの扱う単位を「秒」で揃えているから可能になっています。 Flexでは往々にして、コントロール間で扱う単位を揃えたり 中間に変換するアダプターメソッドを噛ますと、生産性があがりますね。
見た目や精度を向上する
さて、ここまでで一応実装完了しているのですが 使ってみると、ドラッグ中はビデオに再生位置が反映されなかったり 再生位置をスライダーのつまみの位置だけで確認しなければならなかったり ちょっと不親切です。
HSliderにさらに、下の処理を追加。
- liveDragging="true"
- showTrackHighlight="true"
Slider#liveDraggingは、つまみのドラッグ中にもchangeイベントを発行しつづけるためのフラグです。 Slider#showTrackHighlightは、スライダーの始点からつまみまでを色つけするスタイルプロパティ。
完成
以下は全コードです。
- <?xml version="1.0" encoding="utf-8"?>
- <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
- <mx:VBox width="100%" height="100%">
- <mx:VideoDisplay id="myVD"
- source="your.flv"
- width="100%" height="100%"
- />
- <mx:HSlider id="myHS"
- width="100%"
- maximum="{myVD.totalTime}"
- minimum="0"
- value="{myVD.playheadTime}"
- change="{ if(myVD.stateResponsive) myVD.playheadTime = myHS.value }"
- liveDragging="true"
- showTrackHighlight="true"
- />
- </mx:VBox>
- </mx:Application>