Please Wait: An Image-Loading Spinner
This sample shows you how to build an animated spinner that is displayed while loading an image over the network, and then fades away once the image is completely loaded.
Loading an image from Flickr.com
Understanding the Code
The core of this sample is the ImageLoadingSpinner class. It is a custom node which draws a spinner over a particular image. The class monitors the image's progress variable. When the progress reaches 100 the spinner fades away, showing the image underneath. This process is performed by the internal progress variable, as shown in Figure 1.
public class ImageLoadingSpinner extends CustomNode {
public var image:Image;
public var width:Integer = 50;
public var height:Integer = 50;
var spinnerAnim:Timeline;
var fadeAnim:Timeline;
var progress = bind image.progress on replace {
if(progress >= 100) {
fadeAnim.start();
}
}
Figure 1: Monitoring the Image's Progress
The rest of this class creates the actual spinner. It is a group of four circles that rotate around a center. This is done with the code in Figure 2, which loops from 0 to 3, creating a translucent circle offset from the center and rotating by the angle variable plus an offset. When the angle variable is animated the circles are animated as well.
override public function create():Node {
var angle = 0;
var spinner = Group {
content: [
// grey background
Rectangle { width: bind width height: bind height fill: Color.DARKGRAY },
//spinning circles
Group {
translateX: bind width/2
translateY: bind height/2
content: for(n in [0..3]) {
Circle { fill: Color.rgb(255,255,255,0.5)
centerX: 30 centerY: 30 radius: 50 rotate: bind angle+n*90
}
}
}
]
};
spinnerAnim = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: [
at(0s) { angle => 0 tween Interpolator.LINEAR },
at(2s) { angle => 360 tween Interpolator.LINEAR }
]
};
spinnerAnim.start();
Figure 2: Spinner Code
The actual returned node in the create function is a group that contains the image with the spinner on top of it. The fade animation lowers the opacity of the spinner over half a second and stops the animation so that CPU cycles are not wasted.
fadeAnim = Timeline {
keyFrames: [
at(0s) { spinner.opacity => 1.0 tween Interpolator.LINEAR },
KeyFrame {
time: 0.5s values: spinner.opacity => 0.0 tween Interpolator.LINEAR
action: function():Void { spinnerAnim.stop(); }
},
]
};
return Group {
content: [ ImageView { image: image }, spinner ]
}
Figure 3: Fade Animation
Looking Ahead
This example could be extended by creating other spinners with different animation or loading multiple images with a spinner in between them in an animated slideshow.
Josh Marinacci

