Flex純as寫的等待控件

Spinner.as

import flash.events.TimerEvent;

    import flash.utils.Timer;
    
    import mx.core.UIComponent;
    import mx.events.FlexEvent;
    import mx.styles.CSSStyleDeclaration;
    import mx.styles.StyleManager;
    
    //[ExcludeClass]
    
    [Style(name="tickColor", type="uint", format="Color", inherit="no")]
    
    /**
     * Creates a spinning "loader" component that is sort of an indeterminate progress bar.
     * @author Qiang JiShen
     */
    public class Spinner extends UIComponent {
        
        private static var STYLE_TICK_COLOR:String = "tickColor";
        
        private var tickColorChanged:Boolean;
        
        private static var classConstructed:Boolean = classConstruct();
        
        // Make sure we create the ticks the first time updateDisplayList is called
        private var creation:Boolean = true;
        
        
        private var fadeTimer:Timer;
        
        private var _isPlaying:Boolean;
        
        private var _numTicks:int = 24;
        
        private var numTicksChanged:Boolean;
        
        private var _size:Number = 76;
        
        private var sizeChanged:Boolean;
        
        private var _tickWidth:Number = 3;
        
        private var tickWidthChanged:Boolean;
        
        private var _speed:int = 1000;
        
        [Bindable]
        public var fadeSpeed:int = 600;
        
        public var autoPlay:Boolean = true;
        
        
        public function Spinner() {
            super();
            
            //addEventListener(FlexEvent.CREATION_COMPLETE, handleCreationComplete);
        }
        
        private function handleCreationComplete(e:FlexEvent):void {
            removeEventListener(FlexEvent.CREATION_COMPLETE, handleCreationComplete);
            if (autoPlay) {
                play();
            }
        }
        
        
        /**
         * Set the height and width based on the size of the spinner. This should be more robust, but oh well.
         */
        override protected function measure():void {
            super.measure();
            
            width = _size;
            height = _size;
        }
        
        
        /**
         * Override the updateDisplayList method
         */
        override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
            if (tickColorChanged || numTicksChanged || sizeChanged || tickWidthChanged || creation) {
                creation = false;
                // Find out whether it's playing so we can restart it later if we need to
                var wasPlaying:Boolean = _isPlaying;
                
                // stop the spinning
                stop();
                
                // Remove all children
                for (var i:int = numChildren - 1; i >= 0; i--) {
                    removeChildAt(i);
                }
                
                // Re-create the children
                var radius:Number = size / 2;
                var angle:Number = 2 * Math.PI / _numTicks; // The angle between each tick
                var tickWidth:Number = (_tickWidth != -1) ? _tickWidth : size / 10;
                var tickColor:uint = getStyle(STYLE_TICK_COLOR);
                
                var currentAngle:Number = 0;
                for (var j:int = 0; j < _numTicks; j++) {
                    
                    var xStart:Number = radius + Math.sin(currentAngle) * ((_numTicks + 2) * tickWidth / 2 / Math.PI);
                    var yStart:Number = radius - Math.cos(currentAngle) * ((_numTicks + 2) * tickWidth / 2 / Math.PI);
                    var xEnd:Number = radius + Math.sin(currentAngle) * (radius - tickWidth);
                    var yEnd:Number = radius - Math.cos(currentAngle) * (radius - tickWidth);
                    
                    var t:Tick = new Tick(xStart, yStart, xEnd, yEnd, tickWidth, tickColor);
                    t.alpha = 0.1;
                    
                    this.addChild(t);
                    
                    currentAngle += angle;
                }
                
                // Start the spinning again if it was playing when this function was called.
                if (wasPlaying) {
                    play();
                }
                
                tickColorChanged = false;
                numTicksChanged = false;
                sizeChanged = false;
                tickWidthChanged = false;
            }
        }
        
        
        private static function classConstruct():Boolean {
            if (!StyleManager.getStyleDeclaration("Spinner")) {
                // If there is no CSS definition for StyledRectangle,
                // then create one and set the default value.
                var newStyleDeclaration:CSSStyleDeclaration = new CSSStyleDeclaration();
                newStyleDeclaration.setStyle(STYLE_TICK_COLOR, 0x000000);
                StyleManager.setStyleDeclaration("Spinner", newStyleDeclaration, true);
            }
            return true;
        }
        
        override public function styleChanged(styleProp:String):void {
            if (styleProp == STYLE_TICK_COLOR) {
                tickColorChanged = true;
                invalidateDisplayList();
            }
        }
        
        /**
         * Begin the circular fading of the ticks.
         */
        public function play():void {
            if (!_isPlaying) {
                visible = true;
                fadeTimer = new Timer(speed / _numTicks, 0);
                // Anonymous functions are especially useful as simple event handlers
                fadeTimer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void {
                    var tickNum:int = int(fadeTimer.currentCount % _numTicks);
                    
                    if (numChildren > tickNum) {
                        var tick:Tick = getChildAt(tickNum) as Tick;
                        tick.fade(fadeSpeed != 1 ? fadeSpeed : speed * 6 / 10);
                    }
                });
                fadeTimer.start();
                _isPlaying = true;
            }
        }
        
        /**
         * Stop the spinning.
         */
        public function stop():void {
            if (fadeTimer != null && fadeTimer.running) {
                _isPlaying = false;
                visible = false;
                fadeTimer.stop();
            }
        }
        
        /**
         * The overall diameter of the spinner; also the height and width.
         */
        [Bindable]
        public function set size(value:Number):void {
            if (value != _size) {
                _size = value;
                sizeChanged = true;
                invalidateDisplayList();
                invalidateSize();
            }
        }
        
        public function get size():Number {
            return _size;
        }
        
        /**
         * The number of 'spokes' on the spinner.
         */
        [Bindable]
        public function set numTicks(value:int):void {
            if (value != _numTicks) {
                _numTicks = value;
                numTicksChanged = true;
                invalidateDisplayList();
            }
        }
        
        public function get numTicks():int {
            return _numTicks;
        }
        
        /**
         * The width of the 'spokes' on the spinner.
         */
        [Bindable]
        public function set tickWidth(value:int):void {
            if (value != _tickWidth) {
                _tickWidth = value;
                tickWidthChanged = true;
                invalidateDisplayList();
            }
        }
        
        public function get tickWidth():int {
            return _tickWidth;
        }
        
        /**
         * The duration (in milliseconds) that it takes for the spinner to make one revolution.
         */
        [Bindable]
        public function set speed(value:int):void {
            if (value != _speed) {
                _speed = value;
                if (fadeTimer) {
                    fadeTimer.stop();
                    fadeTimer.delay = value / _numTicks;
                    fadeTimer.start();
                }
            }
        }
        
        public function get speed():int {
            return _speed;
        }
        
        
        public function get isPlaying():Boolean {
            return _isPlaying;
        }

    }


Tick.as:


import mx.effects.Fade;
    
    [ExcludeClass]

    /**
     * @author Qiang JiShen
     */
    public class Tick extends Sprite {
        
        private var tickFade:Fade = new Fade(this);

        public function Tick(fromX:Number, fromY:Number, toX:Number, toY:Number, tickWidth:int, tickColor:uint) {
            this.graphics.lineStyle(tickWidth, tickColor, 1.0, false, "normal", "rounded");
            this.graphics.moveTo(fromX, fromY);
            this.graphics.lineTo(toX, toY);
        }

        public function fade(duration:Number):void {
            tickFade.alphaFrom = 1.0;
            tickFade.alphaTo = 0.1;
            tickFade.duration = duration;
            tickFade.play();
        }
    }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章