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); } } BetweenAS3でビデオ的なコントロールを試してみる