Чтобы согласиться с ответом Джонатона Думейна, вот пример класса Spinner
, который я использую в качестве индикатора занятости в своих приложениях.Просто не забудьте вызвать метод stop()
при первой загрузке, поскольку он будет использовать память в вашем приложении, если он воспроизводится, даже если для visible
установлено значение false.Вы можете вызвать метод play()
, если хотите, чтобы он снова начал вращаться.
Spinner.as
package {
import flash.events.TimerEvent;
import flash.utils.Timer;
import mx.core.FlexGlobals;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import mx.styles.CSSStyleDeclaration;
import mx.styles.StyleManager;
[Style(name="tickColor",type="uint",format="Color",inherit="no")]
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 = 12;
private var numTicksChanged:Boolean;
private var _size:Number = 30;
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);
addEventListener(FlexEvent.REMOVE, handleUnloading)
}
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 (!FlexGlobals.topLevelApplication.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);
FlexGlobals.topLevelApplication.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) {
fadeTimer = new Timer(speed / _numTicks, 0);
// addEventListener for the ticking going forward
fadeTimer.addEventListener(TimerEvent.TIMER, handleTicking);
fadeTimer.start();
_isPlaying = true;
}
}
/**
* Start the Tick at each Timer.
*/
public function handleTicking(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);
}
}
/**
* Start the Tick at each Timer.
*/
public function handleUnloading(e:FlexEvent):void {
stop();
removeEventListener(FlexEvent.REMOVE, handleUnloading);
trace("Removing "+this.uid.toString());
}
/**
* Stop the spinning.
*/
public function stop():void {
if (fadeTimer != null && fadeTimer.running) {
_isPlaying = false;
fadeTimer.removeEventListener(TimerEvent.TIMER, handleTicking);
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;
fadeTimer.stop();
fadeTimer.delay = value / _numTicks;
fadeTimer.start();
}
}
public function get speed():int {
return _speed;
}
public function get isPlaying():Boolean {
return _isPlaying;
}
}
}
Tick.as
package {
import flash.display.Sprite;
import mx.effects.Fade;
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();
}
}
}