2009年12月4日

ActionScript3.0でFirefoxのプログレスサークルの作成

Firefoxのタブに表示される読み込み中のアニメーションをActionScript3.0で作成したので公開。

↓(こういうやつ)


FirefoxProgressCircle.as
package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.TimerEvent;
    import flash.utils.Timer;

    /**
     * FirefoxProgressCircle
     */
    public class FirefoxProgressCircle extends Sprite
    {
        /**
         * 回転度数
         */
        protected var _rotate:int = 35;

        /**
         * 円の配置間隔
         */
        protected var _span:int = 45;

        /**
         * 円の半径
         */
        protected var _radius:Number = 1.9;

        /**
         * 円周サイズ
         */
        protected var _size:int = 6;

        /**
         * カラー
         */
        protected var _color:uint = 0x333333;

        /**
         * タイマー
         * 
         * @default null
         */
        protected var _timer:Timer;

        /**
         * サークル
         * 
         * @default null
         */
        protected var _circle:Sprite;

        /**
         * コンストラクタ
         */
        public function FirefoxProgressCircle()
        {
            super();

            // タイマー設定
            this._timer = new Timer(50, 0);
            this._timer.addEventListener(TimerEvent.TIMER, this._onTimer);

            // サークル描画
            this._circle = this._createCircle();

            // 子オブジェクト追加
            this.addChild(this._circle);

            // イベント登録
            this.addEventListener(Event.ADDED_TO_STAGE, this._onStage);
            this.addEventListener(Event.REMOVED,        this._onRemove);
        }

        /**
         * ステージ追加イベント
         * 
         * @param event イベント (OPTIONAL)
         */
        protected function _onStage(event:Event = null):void
        {
            // イベント登録
            this.stage.addEventListener(Event.RESIZE, this._onResize);

            // 位置調整
            this.x = this._size;
            this.y = this._size;
            this._onResize();

            // 回転開始
            this._timer.start();
        }

        /**
         * 削除イベント
         * 
         * @param event イベント (OPTIONAL)
         */
        protected function _onRemove(event:Event = null):void
        {
            // リサイズイベント削除
            if (this.stage.hasEventListener(Event.RESIZE)) {
                this.stage.removeEventListener(Event.RESIZE, this._onResize);
            }
        }

        /**
         * リサイズイベント
         * 
         * @param event イベント (OPTIONAL)
         */
        protected function _onResize(event:Event = null):void
        {
            // 位置調整
            this._circle.x = this.stage.stageWidth / 2 - this._circle.width / 2;
            this._circle.y = this.stage.stageHeight / 2 - this._circle.height / 2;
        }

        /**
         * タイマーイベント
         * 
         * @param event イベント (OPTIONAL)
         */
        protected function _onTimer(event:TimerEvent = null):void
        {
            this._circle.rotation += this._rotate;
        }

        /**
         * サークル生成
         * 
         * @return Spriteオブジェクト
         */
        protected function _createCircle():Sprite
        {
            var circle:Sprite = new Sprite();
            var rotation:int  = 0;
            var cnt:int       = 0;

            // 0~360度を一周するループ処理
            while (rotation < 360) {
                // 一定の間隔で増やし続ける
                rotation += this._span;

                // 角度からラジアンに変換
                var radius:Number = rotation * Math.PI / 180;
                // サイン値を取得
                var sin:Number = Math.sin(radius);
                // コサイン値を取得
                var cos:Number = Math.cos(radius);

                // アルファ
                var alpha:Number = (100 - (cnt * 15)) / 100;

                // サークル描画
                this._drawCircle(circle, sin * this._size, cos * this._size, this._radius, alpha);

                // カウンター
                cnt++;
            }

            return circle;
        }

        /**
         * サークル描画
         *
         * @param obj   対象Sprite
         * @param x     x座標
         * @param y     y座標
         * @param r     ラジアン
         * @param alpha アルファ
         */
        protected function _drawCircle(obj:Sprite, x:Number, y:Number, r:Number, alpha:Number):void
        {
            var s:int = 8;
            var a:Number = Math.tan(Math.PI / s);
            var b:Number = Math.sin(Math.PI / (s / 2));

            obj.graphics.beginFill(this._color, alpha);
            obj.graphics.moveTo(x + r, y);

            obj.graphics.curveTo(r + x, a * r + y, b * r + x, b * r + y);
            obj.graphics.curveTo(a * r + x, r + y, x, r + y);
            obj.graphics.curveTo(-a * r + x, r + y, -b * r + x, b * r + y);
            obj.graphics.curveTo(-r + x, a * r + y, -r + x, y);
            obj.graphics.curveTo(-r + x, -a * r + y, -b * r + x, -b * r + y);
            obj.graphics.curveTo(-a * r + x, -r + y, x, -r + y);
            obj.graphics.curveTo(a * r + x, -r + y, b * r + x, -b * r + y);
            obj.graphics.curveTo(r + x, -a * r + y, r + x, y);

            obj.graphics.endFill();
        }
    }
}


使い方(例:ドキュメントクラスで使用する場合)
// 生成
var circle:FirefoxProgressCircle = new FirefoxProgressCircle();
this.addChild(circle);

// ローディングが終了して不要になったら、ステージから削除すればOK
this.removeChild(circle);

0 件のコメント:

コメントを投稿