BetweenAS3でビデオ的なコントロールを試してみる
package
{
import flash.display.*;
import flash.events.*;
import flash.text.*;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.tweens.ITween;
import org.libspark.betweenas3.events.BetweenEvent;
public class Main extends Sprite
{
public function Main()
{
addEventListener(Event.ADDED_TO_STAGE, initialize);
}
private function initialize(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, initialize);
// トゥイーンさせる矩形を配置
var mc1:Sprite = new Sprite();
mc1.graphics.beginFill(0);
mc1.graphics.drawRect(-10, -10, 10, 10);
mc1.graphics.endFill();
addChild(mc1);
mc1.x = 100;
mc1.y = 100;
var mc2:Sprite = new Sprite();
mc2.graphics.beginFill(0);
mc2.graphics.drawRect(0, -10, 10, 10);
mc2.graphics.endFill();
addChild(mc2);
mc2.x = 100;
mc2.y = 100;
var mc3:Sprite = new Sprite();
mc3.graphics.beginFill(0);
mc3.graphics.drawRect(-10, 0, 10, 10);
mc3.graphics.endFill();
addChild(mc3);
mc3.x = 100;
mc3.y = 100;
var mc4:Sprite = new Sprite();
mc4.graphics.beginFill(0);
mc4.graphics.drawRect(0, 0, 10, 10);
mc4.graphics.endFill();
addChild(mc4);
mc4.x = 100;
mc4.y = 100;
// トゥイーンの動きを記述
var t:ITween = BetweenAS3.parallel(
BetweenAS3.serial(
BetweenAS3.tween(mc1, {$y: 100}, null, 1, Cubic.easeIn),
BetweenAS3.tween(mc1, {$x: 100}, null, 1, Linear.easeNone),
BetweenAS3.tween(mc1, {$x: 200}, {$x: 100}, 1, Linear.easeNone),
BetweenAS3.tween(mc1, {$y: 0}, {$y: 100}, 1, Cubic.easeOut)
),
BetweenAS3.serial(
BetweenAS3.tween(mc2, {$y: 150}, null, 1, Cubic.easeIn),
BetweenAS3.tween(mc2, {$x: 100}, null, 1, Linear.easeNone),
BetweenAS3.tween(mc2, {$x: 200}, {$x: 100}, 1, Linear.easeNone),
BetweenAS3.tween(mc2, {$y: 0}, {$y: 150}, 1, Cubic.easeOut)
),
BetweenAS3.serial(
BetweenAS3.tween(mc3, {$y: 200}, null, 1, Cubic.easeIn),
BetweenAS3.tween(mc3, {$x: 100}, null, 1, Linear.easeNone),
BetweenAS3.tween(mc3, {$x: 200}, {$x: 100}, 1, Linear.easeNone),
BetweenAS3.tween(mc3, {$y: 0}, {$y: 200}, 1, Cubic.easeOut)
),
BetweenAS3.serial(
BetweenAS3.tween(mc4, {$y: 250}, null, 1, Cubic.easeIn),
BetweenAS3.tween(mc4, {$x: 100}, null, 1, Linear.easeNone),
BetweenAS3.tween(mc4, {$x: 200}, {$x: 100}, 1, Linear.easeNone),
BetweenAS3.tween(mc4, {$y: 0}, {$y: 250}, 1, Cubic.easeOut)
)
);
var naturalT:ITween = t; // tの無加工状態をコピーしときます
var reversed:Boolean = false; // リバースしてるかどうか
var scaled:Boolean = false; // スケールしてるかどうか
const SCALE_NUM:Number = 3.5; // 早送り・早戻しでSCALE_NUM倍早く動かす
var tp:Number; // ボタンを押したときにつなぎめなく動かすための、ポジション保持用変数
// コントロールパネルを配置
/* ほんとはコントロールパネルクラスにボタン等の動きを書いて、tの参照を渡すのが
いいんでしょうけど、見易さ重視で! */
var ctrlpanel:ControlPanel = new ControlPanel();
ctrlpanel.y = 400;
addChild(ctrlpanel);
// 再生
ctrlpanel.playBtn.addEventListener(MouseEvent.MOUSE_DOWN,
function():void {
// 1.うごいていたら、いったん停止
if (t.isPlaying) {
t.stop();
}
// 2.現在のポジションを取得して、新しいトゥイーンでのポジションに変換
if (!reversed){
tp = t.position;
}
else {
tp = t.duration - t.position;
}
if (scaled){
tp = tp * SCALE_NUM;
}
// 3.あらかじめコピーしておいたトゥイーンをもとに加工する
t = naturalT;
// 4.ITweenにはisReversedやisScaled(?)みたいなのがないので、そのかわりに。
reversed = false;
scaled = false;
// 5.加工されたトゥイーンを、現状と変わらない位置から再生
t.gotoAndPlay(tp);
// 以下のボタンも同じ構成です
}
);
// 早送り
ctrlpanel.fastPlayBtn.addEventListener(MouseEvent.MOUSE_DOWN,
function():void {
// 1.
if (t.isPlaying) {
t.stop();
}
// 2.
if (!reversed){
tp = t.position;
}
else {
tp = t.duration - t.position;
}
if (!scaled){
tp = tp / SCALE_NUM;
}
// 3.
t = BetweenAS3.scale(naturalT, 1 / SCALE_NUM);
// 4.
reversed = false;
scaled = true;
// 5.
t.gotoAndPlay(tp);
}
);
// 逆再生
ctrlpanel.reverseBtn.addEventListener(MouseEvent.MOUSE_DOWN,
function():void {
// 1.
if (t.isPlaying) {
t.stop();
}
// 2.
if (!reversed){
tp = t.duration - t.position;
}
else {
tp = t.position;
}
if (scaled){
tp = tp * SCALE_NUM;
}
// 3.
t = BetweenAS3.reverse(naturalT);
// 4.
reversed = true;
scaled = false;
// 5.
t.gotoAndPlay(tp);
}
);
// 早戻し
ctrlpanel.fastReverseBtn.addEventListener(MouseEvent.MOUSE_DOWN,
function():void {
// 1.
if (t.isPlaying) {
t.stop();
}
// 2.
if (!reversed){
tp = t.duration - t.position;
}
else {
tp = t.position;
}
if (!scaled){
tp = tp / SCALE_NUM;
}
// 3.
t = BetweenAS3.reverse(BetweenAS3.scale(naturalT, 1 / SCALE_NUM));
// 4.
reversed = true;
scaled = true;
// 5.
t.gotoAndPlay(tp);
}
);
// 一時停止
ctrlpanel.pauseBtn.addEventListener(MouseEvent.MOUSE_DOWN,
function():void {
// うごいていたら停止
if (t.isPlaying) {
t.stop();
}
}
);
// クリックシーク
ctrlpanel.seekBase.addEventListener(MouseEvent.MOUSE_DOWN,
function():void {
var tpos:Number
tpos = ctrlpanel.seekBase.mouseX / ctrlpanel.seekBase.width * naturalT.duration;
if (scaled){
tpos = tpos / SCALE_NUM;
}
if (reversed) {
tpos = t.duration - tpos;
}
if (t.isPlaying) {
t.stop();
t.gotoAndPlay(tpos);
}
else {
t.gotoAndStop(tpos);
}
}
);
// 時間表示
addEventListener(Event.ENTER_FRAME,
function():void {
/* トゥイーンをscaleやreverseすると、t.positionやdurationも
変わってくるので、都合の良いように変換してから表示します */
var tpos:Number;
if (!reversed) {
tpos = t.position;
}
else {
tpos = t.duration - t.position;
}
if (scaled){
tpos = tpos * SCALE_NUM;
}
ctrlpanel.posText.text = tpos.toString().substr(0, 4);
// シークバーにも反映
ctrlpanel.seekBar.width = tpos / naturalT.duration * ctrlpanel.seekBase.width;
}
);
/**
* メモ:
* 時間取得のところは、ほんとはENTER_FRAMEじゃなくて
* t.addEventListener(BetweenEvent.UPDATE,
* のようにするのが良さげなのですが、
* reverseやscaleされたトゥイーンからはイベントがとれないみたいです。
* → 今後対応予定だそうです!
*/
ctrlpanel.durText.text = t.duration.toString().substr(0, 4);
// 以下、絵的な部分 ------------------------------------------------------------------
var startText:TextField = new TextField();
startText.text = "START";
startText.x = 80;
startText.y = 67;
addChild(startText);
var startRect:Shape = new Shape();
startRect.graphics.lineStyle(0,0);
startRect.graphics.moveTo(-15, 15);
startRect.graphics.lineTo(-15, -15);
startRect.graphics.lineTo(15, -15);
startRect.graphics.lineTo(15, 15);
startRect.x = 100;
startRect.y = 100;
addChild(startRect);
var goalText:TextField = new TextField();
goalText.text = "GOAL";
goalText.x = 282;
goalText.y = 67;
addChild(goalText);
var goalRect:Shape = new Shape();
goalRect.graphics.lineStyle(0,0);
goalRect.graphics.moveTo(-15, 15);
goalRect.graphics.lineTo(-15, -15);
goalRect.graphics.lineTo(15, -15);
goalRect.graphics.lineTo(15, 15);
goalRect.x = 300;
goalRect.y = 100;
addChild(goalRect);
}
}
}
import flash.display.*;
import flash.text.*;
class ControlPanel extends Sprite
{
public var playBtn:Sprite;
public var fastPlayBtn:Sprite;
public var reverseBtn:Sprite;
public var fastReverseBtn:Sprite;
public var pauseBtn:Sprite;
public var seekBar:Sprite;
public var seekBase:Sprite;
public var posText:TextField;
public var durText:TextField;
public function ControlPanel()
{
var timeText:TextField = new TextField();
timeText.x = 10;
timeText.y = -5;
timeText.text = "TIME";
addChild(timeText);
posText = new TextField();
posText.autoSize = TextFieldAutoSize.LEFT;
posText.x = 10;
posText.y = 10;
addChild(posText);
durText = new TextField();
durText.autoSize = TextFieldAutoSize.LEFT;
durText.x = 50;
durText.y = 10;
addChild(durText);
playBtn = new Sprite();
playBtn.graphics.beginFill(0xFF00FF);
playBtn.graphics.moveTo(0, 0);
playBtn.graphics.lineTo(30, 20);
playBtn.graphics.lineTo(0, 40);
playBtn.graphics.endFill();
playBtn.buttonMode = true;
addChild(playBtn);
playBtn.x = 305;
var playText:TextField = new TextField();
playText.text = "Play";
addChild(playText);
playText.x = playBtn.x;
playText.y = playBtn.y + 40;
fastPlayBtn = new Sprite();
fastPlayBtn.graphics.beginFill(0xFF00FF);
fastPlayBtn.graphics.moveTo(0, 0);
fastPlayBtn.graphics.lineTo(20, 20);
fastPlayBtn.graphics.lineTo(0, 40);
fastPlayBtn.graphics.moveTo(20, 0);
fastPlayBtn.graphics.lineTo(40, 20);
fastPlayBtn.graphics.lineTo(20, 40);
fastPlayBtn.graphics.endFill();
fastPlayBtn.buttonMode = true;
addChild(fastPlayBtn);
fastPlayBtn.x = 350;
var fastPlayText:TextField = new TextField();
fastPlayText.text = "FastPlay";
addChild(fastPlayText);
fastPlayText.x = fastPlayBtn.x;
fastPlayText.y = fastPlayBtn.y+40;
reverseBtn = new Sprite();
reverseBtn.graphics.beginFill(0xFF00FF);
reverseBtn.graphics.moveTo(40, 0);
reverseBtn.graphics.lineTo(10, 20);
reverseBtn.graphics.lineTo(40, 40);
reverseBtn.graphics.endFill();
reverseBtn.buttonMode = true;
addChild(reverseBtn);
reverseBtn.x = 195;
var reverseText:TextField = new TextField();
reverseText.text = "Reverse";
addChild(reverseText);
reverseText.x = reverseBtn.x;
reverseText.y = reverseBtn.y + 40;
fastReverseBtn = new Sprite();
fastReverseBtn.graphics.beginFill(0xFF00FF);
fastReverseBtn.graphics.moveTo(20, 0);
fastReverseBtn.graphics.lineTo(00, 20);
fastReverseBtn.graphics.lineTo(20, 40);
fastReverseBtn.graphics.moveTo(40, 0);
fastReverseBtn.graphics.lineTo(20, 20);
fastReverseBtn.graphics.lineTo(40, 40);
fastReverseBtn.graphics.endFill();
fastReverseBtn.buttonMode = true;
addChild(fastReverseBtn);
fastReverseBtn.x = 150;
var fastReverseText:TextField = new TextField();
fastReverseText.text = "FastRev";
addChild(fastReverseText);
fastReverseText.x = fastReverseBtn.x;
fastReverseText.y = fastReverseBtn.y+40;
pauseBtn = new Sprite();
pauseBtn.graphics.beginFill(0xFF00FF);
pauseBtn.graphics.moveTo(0, 0);
pauseBtn.graphics.lineTo(15, 0);
pauseBtn.graphics.lineTo(15, 40);
pauseBtn.graphics.lineTo(0, 40);
pauseBtn.graphics.moveTo(25, 0);
pauseBtn.graphics.lineTo(40, 0);
pauseBtn.graphics.lineTo(40, 40);
pauseBtn.graphics.lineTo(25, 40);
pauseBtn.graphics.endFill();
pauseBtn.buttonMode = true;
addChild(pauseBtn);
pauseBtn.x = 250;
var pauseText:TextField = new TextField();
pauseText.text = "Pause";
addChild(pauseText);
pauseText.x = pauseBtn.x;
pauseText.y = pauseBtn.y+40;
seekBase = new Sprite();
seekBase.graphics.beginFill(0xCCCCCC);
seekBase.graphics.drawRect(0,0,400,10);
seekBase.x = 20;
seekBase.y = -20;
seekBase.buttonMode = true;
addChild(seekBase);
seekBar = new Sprite();
seekBar.graphics.beginFill(0xFF00FF);
seekBar.graphics.drawRect(0,0,400,10);
seekBar.x = 20;
seekBar.y = -20;
seekBar.mouseEnabled = false;
addChild(seekBar);
}
}