In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

ProgressBar Illusion

Get Adobe Flash player
by paq 23 Jan 2011
/**
 * Copyright paq ( http://wonderfl.net/user/paq )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/qhUn
 */

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    
    /**
     * どれが一番早くみえるか。
     * 
     * 参考
     * http://gizmodo.com/5719988/the-devious-progress-bar-illusion
     * 
     * @author paq
     */
    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="60")]
    public class ProgressBarIllusion extends Sprite 
    {
        /**
         * コンストラクタ
         */
        public function ProgressBarIllusion() 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private var _progressBars:Vector.<ProgressBar> = new Vector.<ProgressBar>();
        
        /**
         * 初期化します.
         * 
         * <p>この関数は一度だけ呼び出してください。</p>
         * 
         * @param    event
         */
        private function init(event:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            ComponentManager.initialize(new EnterFrameTicker());
            
            _progressBars.push(new ProgressBar(this, 0, 0, ProgressBar.SIMPLE));
            _progressBars.push(new ProgressBar(this, 0, 0, ProgressBar.TWINKLE, 1));
            _progressBars.push(new ProgressBar(this, 0, 0, ProgressBar.TWINKLE, 2));
            _progressBars.push(new ProgressBar(this, 0, 0, ProgressBar.GRADIENT, -1));
            _progressBars.push(new ProgressBar(this, 0, 0, ProgressBar.GRADIENT, 1));
            _progressBars.push(new ProgressBar(this, 0, 0, ProgressBar.GRADIENT, 0));
            _progressBars.push(new ProgressBar(this, 0, 0, ProgressBar.GRADIENT, 0.5));
            _progressBars.push(new ProgressBar(this, 0, 0, ProgressBar.GRADIENT, 3));
            _progressBars.push(new ProgressBar(this, 0, 0, ProgressBar.GRADIENT, 4));
            
            var len:int = _progressBars.length;
            for (var i:int; i < len; i++ )
            {
                _progressBars[i].x = 10;
                _progressBars[i].y = 10 + i * 50;
                _progressBars[i].size(stage.stageWidth - 20, 40);
            }
            
            addEventListener(Event.ENTER_FRAME, loop);
            stage.addEventListener(MouseEvent.CLICK, function():void {
                var len:int = _progressBars.length;
                for (var i:int; i < len; i++ )
                {
                    _progressBars[i].value = 0;
                }
            });
        }
        
        /**
         * フレーム実行ハンドラ
         * 
         * @param    event
         */
        private function loop(event:Event):void 
        {
            var len:int = _progressBars.length;
            for (var i:int; i < len; i++ )
            {
                _progressBars[i].value += 0.001;
            }
        }
    }
    
}

import flash.display.DisplayObjectContainer;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.ColorMatrixFilter;
import flash.geom.Matrix;

class ComponentManager
{
    /**
     * 新しい ComponentManager クラスのインスタンスを作成します
     */
    public function ComponentManager() 
    {
    }
    
    private static var _ticker:ITicker;
    private static var _components:Vector.<Component>;
    
    /**
     * 
     * @param    ticker
     */
    public static function initialize(ticker:ITicker):void
    {
        _ticker = ticker;
        _components = new Vector.<Component>();
    }

    /**
     * 指定されたコンポーネントを追加します
     * 
     * @param    component
     */
    public static function addComponent(component:Component):void
    {
        _components.push(component);
    }
    
    /**
     * 全てのコンポーネントを更新します
     */
    public static function updateAll():void
    {
        var len:int = _components.length;
        for (var i:int = 0; i < len; i++ )
        {
            _components[i].update();
        }
    }
}

interface ITicker
{
    function tick():void;
}

class EnterFrameTicker implements ITicker
{
    /**
     * 新しい EnterFrameTicker クラスのインスタンスを作成します
     */
    public function EnterFrameTicker() 
    {
        _sprite = new Sprite();
        _sprite.addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }
    
    private var _sprite:Sprite;
        
    /**
     * @inheritDoc
     */
    public function tick():void
    {
        ComponentManager.updateAll();
    }
    
    //---------------------------------------------
    // イベントハンドラ
    //---------------------------------------------
    
    /**
     * フレーム実行ハンドラ
     * 
     * @param    event
     */
    private function onEnterFrame(event:Event):void 
    {
        tick();
    }
}

class Component extends Sprite
{
    /**
     * 新しい Component クラスのインスタンスを作成します
     * 
     * @param    parent    DisplayObjectContainer.
     * @param    xpos    コンポーネントのX座標.
     * @param    ypos    コンポーネントのY座標.
     */
    public function Component(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0) 
    {
        if (parent)
        {
            parent.addChild(this);
        }
        
        this.x = xpos;
        this.y = ypos;
        
        initialize();
        
        // コンポーネントマネージャーに追加
        ComponentManager.addComponent(this);
    }
    
    protected var _width:Number;
    protected var _height:Number;
    
    /**
     * コンポーネントの大きさを変更します
     * 
     * @param    w    幅.
     * @param    h    高さ.
     */
    public function size(w:int, h:int):void
    {
        _width = w;
        _height = h;
        dispatchEvent(new Event(Event.RESIZE));
    }
    
    /**
     * コンポーネントを初期化します
     */
    protected function initialize():void
    {
    }
     
    /**
     * コンポーネントを更新します
     */
    public function update():void
    {
    }
    
    /**
     * コンポーネントを正常に戻します
     */
    public function normalize():void
    {
    }
    
    //---------------------------------------------
    // getter / setter
    //---------------------------------------------
    
    override public function get width():Number 
    {
        return _width;
    }
    
    override public function set width(value:Number):void 
    {
        _width = value;
        dispatchEvent(new Event(Event.RESIZE));
    }
    
    override public function get height():Number 
    {
        return _height;
    }
    
    override public function set height(value:Number):void 
    {
        _height = value;
        dispatchEvent(new Event(Event.RESIZE));
    }
}

class ProgressBar extends Component
{
    /**
     * 新しい ProgressBar クラスのインスタンスを作成します
     * 
     * @param    parent    DisplayObjectContainer.
     * @param    xpos    コンポーネントのX座標.
     * @param    ypos    コンポーネントのY座標.
     */
    public function ProgressBar(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, type:String = null, speed:Number = 0) 
    {
        _parent = parent;
        if (type == null || type == "")
        {
            type = SIMPLE;
        }
        _type = type;
        _speed = speed;
        
        super(parent, xpos, ypos);
        
        addEventListener(Event.RESIZE, onResize);
    }
    
    /** もっとも単純な表示方法です */
    public static const SIMPLE:String = "simple";
    
    /** 定期的に光らせます */
    public static const TWINKLE:String = "twinkle";
    private var _twinkle:Number;
    private var _twinkleReverse:Boolean;
    
    /** グラデーションで描画します */
    public static const GRADIENT:String = "gradient";
    private var _gradationX:Number;
    
    private var _type:String;
    
    private var _speed:Number;
    private var _value:Number;
    private var _maxValue:Number;
    
    private var _parent:DisplayObjectContainer;
    private var _bar:Sprite;
    private var _cover:Sprite;
    
    /**
     * @inheritDoc
     */
    override protected function initialize():void
    {
        size(200, 20);
        
        _value = 0.0;
        _maxValue = 1.0;
        
        _gradationX = 0;
        _twinkle = 100;
        _twinkleReverse = false;
        
        _bar = new Sprite();
        _bar.scaleX = 0;
        addChild(_bar);
        
        _cover = new Sprite();
        addChild(_cover);
        
        _cover.mask = _bar;
        
        normalize();
    }
    
    /**
     * @inheritDoc
     */
    override public function update():void
    {
        var percent:Number = _value / _maxValue;
        _bar.scaleX = percent;
        
        var g:Graphics = _cover.graphics;
        
        switch (_type)
        {
            case SIMPLE:
                // 何もしない
                break;
            case TWINKLE:
                // TODO: 色関係をもっとスマートにする
                
                _twinkle -= _speed;
                if (_twinkle < 0)
                {
                    _twinkle = 100;
                    _twinkleReverse = !_twinkleReverse;
                }
                
                var light:uint;
                if (_twinkleReverse)
                {
                    light = 100 - _twinkle;
                }
                else
                {
                    light = _twinkle;
                }
                
                var color:uint = 0x2CA9E1;
                var colorR:uint = (color >> 16 & 0xFF) + light;
                var colorG:uint = (color >> 8 & 0xFF) + light;
                var colorB:uint = (color & 0xFF) + light;
                if (colorR > 255) colorR = 255;
                if (colorG > 255) colorG = 255;
                if (colorB > 255) colorB = 255;
                
                g.clear();
                g.beginFill(colorR << 16 | colorG << 8 | colorB);
                g.drawRect(0, 0, _width, _height);
                break;
            case GRADIENT:
                _gradationX -= _speed;
                g.clear();
                g.beginGradientFill(GradientType.LINEAR,
                    [0x2CA9E1, 0xA0D8EF],
                    [1, 1],
                    [0,    255],
                    new Matrix(0.025, 0, 0, 0, _gradationX),
                    SpreadMethod.REFLECT);
                g.drawRect(0, 0, _width, _height);
                break;
        }
    }
    
    /**
     * @inheritDoc
     */
    override public function normalize():void
    {
        var g:Graphics;
        
        g = _bar.graphics;
        g.clear();
        g.beginFill(0x000000);
        g.drawRect(0, 0, _width, _height);
        
        g = _cover.graphics;
        g.clear();
        
        switch (_type)
        {
            case SIMPLE:
                g.beginFill(0x2ca9e1);
                g.drawRect(0, 0, _width, _height);
                break;
            case TWINKLE:
                g.beginFill(0x2ca9e1);
                g.drawRect(0, 0, _width, _height);
                break;
            case GRADIENT:
                // 何もしない
                break;
        }
    }
    
    //---------------------------------------------
    // イベントハンドラ
    //---------------------------------------------
    
    /**
     * リサイズされたときに呼び出されます
     * 
     * @param    event
     */
    private function onResize(event:Event):void 
    {
        normalize();
    }
    
    //---------------------------------------------
    // getter / setter
    //---------------------------------------------
    
    public function get value():Number 
    {
        return _value;
    }
    
    public function set value(value:Number):void 
    {
        _value = value;
        if (_value > _maxValue)
        {
            _value = _maxValue;
        }
    }
    
    public function get maxValue():Number 
    {
        return _maxValue;
    }
    
    public function set maxValue(value:Number):void 
    {
        _maxValue = value;
    }
}