How to specify SWF instead of an image in loading
nikolaig Jul 17, 2012 6:50 AMI hope it is not too much over my head as I would like to make it work. Some time ago I recieved help in constracting an interactive image thumb scroller using greensock features.
My biggest problem at the moment is that I can not figure out how to change the code so the thumbs would bring up the swf files and not jpg files. In other words my small thumbnails are small jpg files (as they were intended to be), but my bigger visuals (the ones which are being brought by clicking on the small thumbnails) I would like to change to an swf file (as it contains its separate animation and additional set of buttons)
Here is the original code I am trying to modify:
[CODE]
package {
import com.greensock.TweenLite;
import com.greensock.events.LoaderEvent;
import com.greensock.loading.ImageLoader;
import com.greensock.loading.LoaderMax;
import com.greensock.loading.XMLLoader;
import com.greensock.plugins.AutoAlphaPlugin;
import com.greensock.plugins.ColorTransformPlugin;
import com.greensock.plugins.GlowFilterPlugin;
import com.greensock.plugins.TweenPlugin;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class SlideshowExample extends MovieClip {
private static const _THUMB_WIDTH:Number = 100;
private static const _THUMB_HEIGHT:Number = 64;
private static const _IMAGE_WIDTH:Number = 550;
private static const _IMAGE_HEIGHT:Number = 355;
private static const _THUMB_GAP:Number = 4;
private static const _SCROLL_SPEED:Number = 12;
private static const _SCROLL_AREA:Number = 150;
private var _progressBar:MovieClip;
private var _arrowLeft:MovieClip;
private var _arrowRight:MovieClip;
private var _slides:Array;
private var _curSlide:Slide; //Slide that is currently displaying
private var _loadingSlide:Slide; //only used when a Slide is supposed to show but hasn't been fully loaded yet (like if the user clicks "next" many times before all the images have loaded). We keep track of the one that's in the process of loading and should be shown as soon as it finishes, then we set _loadingSlide back to null.
private var _imagesContainer:Sprite; //the Sprite into which the full-size images are placed (this helps manage the stacking order so that the images can always be behind everything else and yet we can addChild() each image so that it shows up on top of the previous one)
private var _thumbnailsContainer:Sprite; //the Sprite into which the thumbnail images are placed. This also allows us to slide them all at the same time.
private var _destScrollX:Number = 0; //destination x value for the _thumbnailsContainer which is used for scrolling it across the bottom. We don't want to use _thumbnailsContainer.x because it could be in the process of tweening, so we keep track of the end/destination value and add/subtract from it when creating our tweens.
private var _minScrollX:Number; //we know the maximum x value for _thumbnailsContainer is 0, but the mimimum value will depend on how many thumbnail images it contains (the total width). We calculate it in the _setupThumbnails() method and store it here for easier/faster scrolling calculations in the _enterFrameHandler()
public function SlideshowExample() {
super();
//activate the plugins that we'll be using so that TweenLite can tween special properties like filters, colorTransform, and do autoAlpha fades.
TweenPlugin.activate([AutoAlphaPlugin, ColorTransformPlugin, GlowFilterPlugin]);
_progressBar = this.getChildByName("progress_mc") as MovieClip;
_arrowLeft = this.getChildByName("arrowLeft_mc") as MovieClip;
_arrowRight = this.getChildByName("arrowRight_mc") as MovieClip;
_arrowLeft.visible = _arrowRight.visible = false;
_imagesContainer = new Sprite();
this.addChildAt(_imagesContainer, 0);
_thumbnailsContainer = new Sprite();
addChild(_thumbnailsContainer);
_thumbnailsContainer.y = _IMAGE_HEIGHT;
_thumbnailsContainer.alpha = 0; //we want alpha 0 initially because we'll fade it in later when the thumbnails load.
_thumbnailsContainer.visible = false; //ensures nothing is clickable.
var xmlLoader:XMLLoader = new XMLLoader("assets/data.xml", {onComplete:_xmlCompleteHandler});
xmlLoader.load();
}
private function _xmlCompleteHandler(event:LoaderEvent):void {
_slides = [];
var xml:XML = event.target.content; //the XMLLoader's "content" is the XML that was loaded.
var imageList:XMLList = xml.image; //In the XML, we have <image /> nodes with all the info we need.
//loop through each <image /> node and create a Slide object for each.
for each (var image:XML in imageList) {
_slides.push( new Slide(image.@name,
image.@description,
new ImageLoader("assets/thumbnails/" + image.@name + ".jpg", {name:image.@name + "Thumb", width:_THUMB_WIDTH, height:_THUMB_HEIGHT, scaleMode:"proportionalInside", bgColor:0x000000, estimatedBytes:13000, onFail:_imageFailHandler}),
new ImageLoader("assets/images/" + image.@name + ".jpg", {name:image.@name + "Image", width:_IMAGE_WIDTH, height:_IMAGE_HEIGHT, scaleMode:"proportionalInside", bgColor:0x000000, estimatedBytes:820000, onFail:_imageFailHandler})
)
);
}
//now create a LoaderMax queue and populate it with all the thumbnail ImageLoaders as well as the very first full-size ImageLoader. We don't want to show anything until the thumbnails are done loading as well as the first full-size one. After that, we'll create another LoaderMax queue containing the rest of the full-size images that will load silently in the background.
var initialLoadQueue:LoaderMax = new LoaderMax({onComplete:_initialLoadComplete, onProgress:_progressHandler});
for (var i:int = 0; i < _slides.length; i++) {
initialLoadQueue.append( _slides[i].thumbnailLoader );
}
initialLoadQueue.append(_slides[0].imageLoader); //make sure the very first full-sized image is loaded initially too.
initialLoadQueue.load();
_setupThumbnails();
}
private function _initialLoadComplete(event:LoaderEvent):void {
//now that the initial load is complete, fade out the progressBar. autoAlpha will automatically set visible to false once alpha hits 0.
TweenLite.to(_progressBar, 0.5, {autoAlpha:0});
//fade in the thumbnails container
TweenLite.to(_thumbnailsContainer, 1, {autoAlpha:1});
_setupArrows();
//setup the ENTER_FRAME listeners that controls the thumbnail scrolling behavior at the bottom
this.stage.addEventListener(Event.ENTER_FRAME, _enterFrameHandler, false, 0, true);
//now put all the remaining images into a LoaderMax queue that will load them one-at-a-time in the background in the proper order. This can greatly improve the user's experience compared to loading them on demand which forces the user to wait while the next image loads.
var imagesQueue:LoaderMax = new LoaderMax({maxConnections:1});
for (var i:int = 1; i < _slides.length; i++) {
imagesQueue.append( _slides[i].imageLoader );
}
imagesQueue.load();
//now start the slideshow
_showNext(null);
}
//loops through all the thumbnail images and places them in the proper order across the bottom of the screen and adds CLICK_THUMBNAIL listeners.
private function _setupThumbnails():void {
var l:int = _slides.length;
var curX:Number = _THUMB_GAP;
for (var i:int = 0; i < l; i++) {
var thumbnail:Sprite = _slides[i].thumbnail;
_thumbnailsContainer.addChild(thumbnail);
TweenLite.to(thumbnail, 0, {colorTransform:{brightness:0.5}});
_slides[i].addEventListener(Slide.CLICK_THUMBNAIL, _clickThumbnailHandler, false, 0, true);
thumbnail.x = curX;
thumbnail.y = 4;
curX += _THUMB_WIDTH + _THUMB_GAP;
}
_minScrollX = _IMAGE_WIDTH - curX;
if (_minScrollX > 0) {
_minScrollX = 0;
}
}
private function _setupArrows():void {
_arrowLeft.alpha = _arrowRight.alpha = 0;
_arrowLeft.visible = _arrowRight.visible = true;
_arrowLeft.addEventListener(MouseEvent.ROLL_OVER, _rollOverArrowHandler, false, 0, true);
_arrowLeft.addEventListener(MouseEvent.ROLL_OUT, _rollOutArrowHandler, false, 0, true);
_arrowLeft.addEventListener(MouseEvent.CLICK, _showPrevious, false, 0, true);
_arrowRight.addEventListener(MouseEvent.ROLL_OVER, _rollOverArrowHandler, false, 0, true);
_arrowRight.addEventListener(MouseEvent.ROLL_OUT, _rollOutArrowHandler, false, 0, true);
_arrowRight.addEventListener(MouseEvent.CLICK, _showNext, false, 0, true);
}
private function _showNext(event:Event=null):void {
//if there's a _loadingSlide we should assume that the next Slide would be AFTER that one. Otherwise just get the one after the _curSlide.
var next:int = (_loadingSlide != null) ? _slides.indexOf(_loadingSlide) + 1 : _slides.indexOf(_curSlide) + 1;
if (next >= _slides.length) {
next = 0;
}
_requestSlide(_slides[next]);
}
private function _showPrevious(event:Event=null):void {
//if there's a _loadingSlide we should assume that the previous Slide would be BEFORE that one. Otherwise just get the one before the _curSlide.
var prev:int = (_loadingSlide != null) ? _slides.indexOf(_loadingSlide) - 1 : _slides.indexOf(_curSlide) - 1;
if (prev < 0) {
prev = _slides.length - 1;
}
_requestSlide(_slides[prev]);
}
private function _requestSlide(slide:Slide):void {
if (slide == _curSlide) {
return;
}
//kill the delayed calls to _showNext so that we start over again with a 5-second wait time.
TweenLite.killTweensOf(_showNext);
if (_loadingSlide != null) {
_cancelPrioritizedSlide(); //the user must have skipped to another Slide and didn't want to wait for the one that was loading.
}
//if the requested Slide's full-sized image hasn't loaded yet, we need to show the progress bar and wait for it to load.
if (slide.imageLoader.progress != 1) {
_prioritizeSlide(slide);
return;
}
//fade the old Slide and make sure it's not highlighted anymore as the current Slide.
if (_curSlide != null) {
TweenLite.to(_curSlide.image, 0.5, {autoAlpha:0});
_curSlide.setShowingStatus(false);
}
_curSlide = slide;
_imagesContainer.addChild(_curSlide.image); //ensures the image is at the top of the stacking order inside the _imagesContainer
TweenLite.to(_curSlide.image, 0.5, {autoAlpha:1}); //fade the image in and make sure visible is true.
_curSlide.setShowingStatus(true); //adds an outline to the image indicating that it's the currently showing Slide.
TweenLite.delayedCall(5, _showNext); //create a delayedCall that will call _showNext in 5 seconds.
}
private function _prioritizeSlide(slide:Slide):void {
TweenLite.to(_progressBar, 0.5, {autoAlpha:1}); //show the progress bar
_loadingSlide = slide;
_loadingSlide.imageLoader.addEventListener(LoaderEvent.PROGRESS, _progressHandler);
_loadingSlide.imageLoader.addEventListener(LoaderEvent.COMPLETE, _completePrioritizedHandler);
_loadingSlide.imageLoader.prioritize(true); //when the loader is prioritized, it will jump to the top of any LoaderMax queues that it belongs to, so if another loader is in the process of loading in that queue, it will be canceled and this new one will take over which maximizes bandwidth utilization. Once the _loadingSlide is done loading, the LoaderMax queue(s) will continue loading the rest of their images normally.
}
private function _cancelPrioritizedSlide():void {
TweenLite.to(_progressBar, 0.5, {autoAlpha:0}); //hide the progress bar
_loadingSlide.imageLoader.removeEventListener(LoaderEvent.PROGRESS, _progressHandler);
_loadingSlide.imageLoader.removeEventListener(LoaderEvent.COMPLETE, _completePrioritizedHandler);
_loadingSlide = null;
}
private function _completePrioritizedHandler(event:LoaderEvent):void {
var next:Slide = _loadingSlide; //store it in a local variable first because _cancelPrioritizedSlide() will set _loadingSlide to null.
_cancelPrioritizedSlide();
_requestSlide(next);
}
private function _progressHandler(event:LoaderEvent):void {
_progressBar.progressBar_mc.scaleX = event.target.progress;
}
private function _clickThumbnailHandler(event:Event):void {
_requestSlide(event.target as Slide);
}
private function _rollOverArrowHandler(event:Event):void {
TweenLite.to(event.currentTarget, 0.5, {alpha:1});
}
private function _rollOutArrowHandler(event:Event):void {
TweenLite.to(event.currentTarget, 0.5, {alpha:0});
}
private function _enterFrameHandler(event:Event):void {
if (_thumbnailsContainer.hitTestPoint(this.stage.mouseX, this.stage.mouseY, false)) {
if (this.mouseX < _SCROLL_AREA) {
_destScrollX += ((_SCROLL_AREA - this.mouseX) / _SCROLL_AREA) * _SCROLL_SPEED;
if (_destScrollX > 0) {
_destScrollX = 0;
}
TweenLite.to(_thumbnailsContainer, 0.5, {x:_destScrollX});
} else if (this.mouseX > _IMAGE_WIDTH - _SCROLL_AREA) {
_destScrollX -= ((this.mouseX - (_IMAGE_WIDTH - _SCROLL_AREA)) / _SCROLL_AREA) * _SCROLL_SPEED;
if (_destScrollX < _minScrollX) {
_destScrollX = _minScrollX;
}
TweenLite.to(_thumbnailsContainer, 0.5, {x:_destScrollX});
}
}
}
//if an image fails to load properly, remove it from the slideshow completely including its thumbnail at the bottom.
private function _imageFailHandler(event:LoaderEvent):void {
var slide:Slide;
var i:int = _slides.length;
while (--i > -1) {
slide = _slides[i];
if (event.target == slide.thumbnailLoader || event.target == slide.imageLoader) {
slide.dispose();
_slides.splice(i, 1);
_setupThumbnails();
return;
}
}
}
}
}
[/CODE]
I could figure out that I have to change the line
[CODE]
new ImageLoader("assets/images/" + image.@name + ".jpg", {name:image.@name + "Image", width:_IMAGE_WIDTH, height:_IMAGE_HEIGHT, scaleMode:"proportionalInside", bgColor:0x000000, estimatedBytes:820000, onFail:_imageFailHandler}
[/CODE]
and instead of ".jpg" put ".swf" (making sure that the names of the files are identical except for their extensions)
The problem is that I get an error message in the output that flash could not convert my swf file to the bitmap.
I suspect that I have to change the hard coding to specify that Loader Max should treat loading bigger swf files as swf and not as image/jpg files.
I don't have enough expertise to decipher all the lines where this has to be changed.
It feels that I am close to accomplishing what I need. Is it possible to point out where this change has to take place?
Here is my thought process:
I don't need to specify SWFLoader as LoaderMax is already specified (line 5)
I don't need to change anything in lines 31-34 as "Sprite" and "Slide" could be an .swf file (line31-34)
I don't need to change anything in line 50 for the same reason (line 50)
I don't need to change lines 66 and 68 as image list may contain swf files (line 66 and 68)
I do need to change ".jpg" to ".swf" in line 72 (line 72)
No sure if there are any changes in line 82 (line 82)
LoaderMax has var as imagesQueue does that need to be changed into SFWLoader? (lines98-102)
I don't think anything need to be changed in lines 138-173 as " Slide" can incorporate an SWF file (lines 138-173)
Not sure if there has to be a change in lines 175-177 as it specifies that slide is an image (lines 175-177)
Not sure if there has to be a change in lines 182-200 from imageLoager to SWFLoader (lines 182-200)
Not sure if there has to be a change in lines 239-245 in specifying SWFLoader (lines 239-245)
I am attaching the .xml and .as documents as well


