カテゴリー別アーカイブ: ActionScript 3.0

ActionScript 3.0 包含イベント

久々のActionScript 3.0ネタ…

ActionScript 3.0には, DisplayObjectが追加されたり, 削除されたりしたときに発生するイベントがあります.

Event Description Bubbling
Event.ADDED DisplayObjectが (子孫として) 追加されたときに発生
Event.REMOVED (子孫の) DisplayObjectが削除されたときに発生
Event.ADDED_TO_STAGE DisplayObjectがstageに追加されたときに発生 ×
Event.REMOVED_FROM_STAGE DisplayObjectがstageから削除されたときに発生 ×

Action Audio APIのモジュール追加

ActionScript 3.0でWeb Audio APIをシミュレートするライブラリであるAction Audio APIに, AudioBuffer.as と AudioBufferSourceNode.as を追加しました.

また, AudioContextインスタンスにdecodeAudioDataメソッドも追加しました.

使い方はほとんどWeb Audio APIと同じです. ただし, decodeAudioDataの第1引数にはSoundインスタンスを指定します.

import flash.events.Event;
import flash.media.Sound;
import flash.net.URLRequest;
import audioapi.AudioContext;
import audioapi.AudioBuffer;
import audioapi.audionodes.AudioBufferSourceNode
import audioapi.audionodes.GainNode;

var context:AudioContext = new AudioContext(stage.frameRate);

trace(context.sampleRate);

var gain:GainNode = context.createGain();

var sound:Sound = new Sound();

sound.addEventListener(Event.COMPLETE, function(event:Event):void {
    context.decodeAudioData(sound, function(audioBuffer:AudioBuffer):void {
        var source:AudioBufferSourceNode = context.createBufferSource();

        source.buffer = audioBuffer;

        source.connect(gain);
        gain.connect(context.destination);

        source.start();
    }, function():void {
    });
}, false, 0, true);

sound.load(new URLRequest('sample.mp3'));

ActionScript 3.0 ビデオプレイヤーで時間関連の値を取得・設定する

まずは, オーディオのトータル時間, つまり, HTML5のHTMLVideoElementのdurationプロパティに相当する値

var netConnection:NetConnection = new NetConnection();
netConnection.connect(null);

var netStream:NetStream = new NetStream(netConnection);
 
infoClients            = new Object();
infoClients.onMetaData = function onmetadata(info:Object):void {
    var duration:Number = info.duration;
};

netStream.client = infoClients;
 
netConnection.addEventListener(NetStatusEvent.NET_STATUS, onnetstatus, false, 0, true); 
netStream.addEventListener(NetStatusEvent.NET_STATUS,     onnetstatus, false, 0, true);
 
var video:Video = new Video();
video.attachNetStream(netStream);
addChild(video);

ビデオの現在再生位置, つまり, HTML5のHTMLVideoElementのcurrentTimeプロパティに相当する値. ただし, 取得と設定が異なります.

取得する場合は, NetStreamインスタンスのtimeプロパティンにアクセスします.

var currentTime:Number = netStream.time;

設定する場合は, NetStreamインスタンスのseekメソッドを利用します.

netStream.seek(currentTime + 1);

ActionScript 3.0 オーディオのループ再生

ActionScript3.0でオーディオをループ再生するには, SoundChannelインスタンスのEvent.SOUND_COMPLETEイベントを監視する.

var sound:Sound = new Sound();

sound.addEventListener(Event.COMPLETE, function(event:Event):void {
    var loop:Boolean = true;
    var rate:Number         = sound.bytesTotal / sound.bytesLoaded;
    var durationMsec:Number = sound.length / rate;  // msec
    var duration:Number     = Math.floor(durationMsec / 1000);  // msec -> sec

    var channel:SoundChannel = sound.play();
    var currentTimeMsec:Number = channel.position;  // msec
    var currentTime:Number     = currentTimeMsec / 1000;  // msec -> sec

    channel.addEventListener(Event.SOUND_COMPLETE, function(event:Event):void {
        if (loop) {
             channel = sound.play(0);
        } else {
             channel.stop();
        }
    }, false, 0, true);
try {
    sound.load(new URLRequest('sample.mp3'));
} catch (error:Error) {
    trace(error.message);
}

ActionScript 3.0 Soundインスタンスから時間関連の値を取得する

まずは, オーディオのトータル時間, つまり, HTML5のHTMLAudioElementのdurationプロパティに相当する値

var sound:Sound = new Sound();

sound.addEventListener(Event.COMPLETE, function(event:Event):void {
    var rate:Number         = sound.bytesTotal / sound.bytesLoaded;
    var durationMsec:Number = sound.length / rate;  // msec
    var duration:Number     = Math.floor(durationMsec / 1000);  // msec -> sec
}, false, 0, true);

try {
    sound.load(new URLRequest('sample.mp3'));
} catch (error:Error) {
    trace(error.message);
}

オーディオの現在再生位置, つまり, HTML5のHTMLAudioElementのcurrentTimeプロパティに相当する値.
これは, SoundChannelインスタンスのポジションプロパティにアクセスするだけです. ただし, これはmsec単位なので, sec単位で取得したい場合は, 変換が必要です.

var sound:Sound = new Sound();

sound.addEventListener(Event.COMPLETE, function(event:Event):void {
    var rate:Number         = sound.bytesTotal / sound.bytesLoaded;
    var durationMsec:Number = sound.length / rate;  // msec
    var duration:Number     = Math.floor(durationMsec / 1000);  // msec -> sec

    var channel:SoundChannel = sound.play();
    var currentTimeMsec:Number = channel.position;  // msec
    var currentTime:Number     = currentTimeMsec / 1000;  // msec -> sec
}, false, 0, true);

try {
    sound.load(new URLRequest('sample.mp3'));
} catch (error:Error) {
    trace(error.message);
}

ActionScript 3.0 ビデオプレイヤークラス

ActionScript 3.0でビデオプレイヤーのためのクラスを作成してみた.

使い方はこんな感じ

import flash.display.Sprite;
import flash.display.SimpleButton;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import fl.motion.Color;
import classes.VideoPlayer

var video:VideoPlayer = new VideoPlayer();

var progress:TextField = new TextField();

var textFormat:TextFormat = new TextFormat();
textFormat.font = 'Helvetica';
textFormat.size = 24;
textFormat.color = 0x999999;
textFormat.align = TextFormatAlign.CENTER;

progress = new TextField();
progress.autoSize = TextFieldAutoSize.LEFT;
progress.defaultTextFormat = textFormat;

addChild(progress);

var duration:String = '00 : 00';
var currentTime:String = '00 : 00';

video.onerror = function(event:IOErrorEvent):void {
 var error:TextField = new TextField();
 error.defaultTextFormat = textFormat;
 error.text = event.text;

 addChild(error);
};

video.ondurationchange = function():void {
 var minutes:String = ('0' + Math.floor(video.duration / 60)).slice(-2);
 var seconds:String = ('0' + Math.floor(video.duration % 60)).slice(-2);

 duration = minutes + ' : ' + seconds;

 progress.text = currentTime + ' / ' + duration;
}

video.ontimeupdate = function():void {
 var minutes:String = ('0' + Math.floor(video.currentTime / 60)).slice(-2);
 var seconds:String = ('0' + Math.floor(video.currentTime % 60)).slice(-2);

 currentTime = minutes + ' : ' + seconds;

 progress.text = currentTime + ' / ' + duration;
};

video.onended = function(event:Event) {
 currentTime = '00 : 00';
}

video.src = 'kurenai-twin.mp4';

video.x = stage.stageWidth / 4;
video.y = stage.stageHeight / 4;

addChild(video);

createControlButtons();

function createControlButtons() {
 var playButton:Sprite = createButton(80, 20, 10, 2, 0x0066CC, 'Play', 0xFFFFFF);
 var pauseButton:Sprite = createButton(80, 20, 10, 2, 0x0066CC, 'Pause', 0xFFFFFF);
 var stopButton:Sprite = createButton(80, 20, 10, 2, 0x0066CC, 'Stop', 0xFFFFFF);

 playButton.x = 170;
 playButton.y = 365;

 pauseButton.x = 310;
 pauseButton.y = 365;

 stopButton.x = 450;
 stopButton.y = 365;

 playButton.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void {video.play();}, false, 0, true);
 pauseButton.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void {video.pause();}, false, 0, true);
 stopButton.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void {}, false, 0, true);

 addChild(playButton);
 addChild(pauseButton);
 addChild(stopButton);
}

function createButton(width:Number, height:Number, radius:Number, lineWidth:Number, color:uint, text:String, textColor:uint):Sprite {
 var overColor:uint = Color.interpolateColor(color, 0xFFFFFF, 0.3);
 var downColor:uint = Color.interpolateColor(color, 0x000000, 0.3);

 var buttonWrapper:Sprite = new Sprite();

 var button:SimpleButton = new SimpleButton();

 //button.buttonMode = true;
 //button.useHandCursor = true;

 button.upState = createRoundButton(width, height, radius, lineWidth, color);
 button.overState = createRoundButton(width, height, radius, lineWidth, overColor);
 button.downState = createRoundButton(width, height, radius, lineWidth, downColor);
 button.hitTestState = button.upState;

 var textField:TextField = new TextField();

 var textFormat:TextFormat = new TextFormat();

 textFormat.font = 'Helvetica';
 textFormat.size = 10;
 textFormat.color = textColor;
 textFormat.align = TextFormatAlign.CENTER;

 textField.y = 4;
 textField.width = width;
 textField.height = height;
 textField.defaultTextFormat = textFormat;
 textField.text = text;

 textField.selectable = false;
 textField.mouseEnabled = false;

 buttonWrapper.addChild(button);
 buttonWrapper.addChild(textField);

 return buttonWrapper;
}

function createRoundButton(width:Number, height:Number, radius:Number, lineWidth:Number, color:uint):Sprite {
 var button:Sprite = new Sprite();

 button.graphics.lineStyle(lineWidth, color);
 button.graphics.beginFill(color, 0.5)
 button.graphics.drawRoundRect(0, 0, width, height, radius);
 button.graphics.endFill();

 return button;
}

stage.addEventListener(KeyboardEvent.KEY_DOWN, function(event:KeyboardEvent):void {
 switch (event.keyCode) {
 case Keyboard.UP :
 video.volume += 0.05;
 break;
 case Keyboard.DOWN :
 video.volume -= 0.05;
 break;
 case Keyboard.SPACE :
 video.muted = !video.muted;
 trace('MUTE : ' + video.muted);
 break;
 case Keyboard.SHIFT :
 video.loop = !video.loop;
 trace('LOOP : ' + video.loop);
 break;
 case Keyboard.PERIOD :
 video.currentTime += 1;
 break;
 case Keyboard.COMMA :
 video.currentTime -= 1;
 break;
 default :
 break;
 }
}, false, 0, true);

HTML5 VideoをシミュレーションするようなAPIにしています.

ActionScript 3.0 オーディオビジュアライザーのクラス

ActionScript 3.0 でオーディオビジュアライザーのクラスを作成してみた.

実質的に波形描画を担うのは, AnalyserNode.asのほうです.

使い方はこんな感じ.

import classes.AudioVisualizer;

var options:Object = {
    left   : 120,
    right : 120,
    fft    : false
};

var visualizer:AudioVisualizer = new AudioVisualizer('sample.mp3', options);

addChild(visualizer);

スペクトルを表示したい場合は, オプションのfftをtrueにする.

ActionScript 3.0 オーディオ再生のためのクラス

ActionScript 3.0でオーディオ再生のためのクラスを作成してみた.

使い方はこんな感じ

import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import classes.Audio;

var audio:Audio = new Audio();

var progress:TextField = null;
var duration:String    = '00 : 00';
var currentTime:String = '00 : 00';

audio.onprogress = function(event:ProgressEvent):void {
    var rate:Number = Math.floor(event.bytesLoaded * 100 / event.bytesTotal);

    if (progress == null) {
        var textFormat:TextFormat = new TextFormat();
        textFormat.font  = 'Helvetica';
        textFormat.size  = 24;
        textFormat.color = 0x999999;
        textFormat.align = TextFormatAlign.CENTER;

        progress                   = new TextField();
        progress.autoSize          = TextFieldAutoSize.LEFT;
        progress.defaultTextFormat = textFormat;

        addChild(progress);
     }

    progress.text = rate + ' %';
};

audio.onerror = function(event:IOErrorEvent):void {
    var textFormat:TextFormat = new TextFormat();
    textFormat.font = 'Helvetica';
    textFormat.size = 24;
    textFormat.color = 0x999999;
    textFormat.align = TextFormatAlign.CENTER;

    var error:TextField    = new TextField();
    error.defaultTextFormat = textFormat;
    error.text              = event.text;

    addChild(error);
};

audio.oncanplay = function(event):void {
    stage.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void {
        if (audio.paused) {
            audio.play(audio.currentPosition);
        } else {
            audio.pause();
        }
    }, false, 0, true);
};

audio.ondurationchange = function(event:Event):void {
    var minutes:String = ('0' + Math.floor(audio.duration / 60)).slice(-2);
    var seconds:String = ('0' + Math.floor(audio.duration % 60)).slice(-2);

    duration = minutes + ' : ' + seconds;

    progress.text = currentTime + ' / ' + duration;
}

audio.ontimeupdate = function():void {
    var minutes:String = ('0' + Math.floor(audio.currentTime / 60)).slice(-2);
    var seconds:String = ('0' + Math.floor(audio.currentTime % 60)).slice(-2);

    currentTime = minutes + ' : ' + seconds;

    progress.text = currentTime + ' / ' + duration;
};

audio.onended = function(event:Event) {
    currentTime = '00 : 00';
}

stage.addEventListener(KeyboardEvent.KEY_DOWN, function(event:KeyboardEvent):void {
    switch (event.keyCode) {
        case Keyboard.UP :
            audio.volume += 0.05;
            break;
        case Keyboard.DOWN :
            audio.volume -= 0.05;
            break;
        case Keyboard.LEFT :
            audio.pan -= 0.1;
            break;
        case Keyboard.RIGHT :
            audio.pan += 0.1;
            break;
        case Keyboard.SPACE :
            audio.muted = !audio.muted;
            trace('MUTE : ' + audio.muted);
            break;
        case Keyboard.SHIFT :
            audio.loop = !audio.loop;
            trace('LOOP : ' + audio.loop);
            break;
        case Keyboard.PERIOD :
            audio.currentTime += 1;
            break;
        case Keyboard.COMMA :
            audio.currentTime -= 1;
            break;
        default :
            break;
    }
}, false, 0, true);

audio.src = 'sample.mp3';

addChild(audio);

HTML5 AudioをシミュレーションするようなAPIにしています.