Loading Remote Images into the Slider
In the previous example, we looked at loading images that were locally available. This time, we will look at loading images from a remote location. The main difference in this scenario is that we will need to preload the images before setting the castmember fileName (otherwise the image of the linked file will not be available).
Like the previous example, the first step is to get a list of files to load. However, unlike the local file example, this cannot be done by shockwave: We need to create a server-side script (in, ASPX etc) to return that list and use some net lingo to get the list. Here is an example script to lists the images in a directory:
SCRIPT]
$rootpath = "/Path/to/SliderImages";
$url = "http://URL/to/SliderImage";
$listableExts = array('jpg','gif','png','jpeg');
$dir = opendir($rootpath);
$out = "[";
while ($thisfile = readdir($dir)) {
$fname = "$rootpath/$thisfile";
if (is_file($fname)) {
if(strpos($thisfile,'.')!==false){
$ext = explode('.',$thisfile);
if(in_array(strtolower($ext[count($ext)-1]), $listableExts)){
$out .=""$url/$thisfile",";
}
}
}
}
closedir($dir);
$out = rtrim($out, ","). "]";
echo $out;
If you dont have access to any server side scripts, you could just use a text file that contains a list of all the images. If you want to add more images, simply edit the text file.
To retreive this list of images, we will need to use an object to handle a Network operation. Once we have the list of files, we need to go through a preload each file.
Here is the behaviour that inherits the "HorizontalSlider.class" discussed previously. As part of its initialise process, it creates an "imageLoader" object and tells this imageLoader the URL to get the list of images from.
-- create an Object to load up the images
-- #### CHANGE THIS TO YOUR SERVER ADDRESS ####
imageListSource = "http://vs4/GetImageList?";
imageLoaderDaemon = script("ImageLoader.NET").new()
imageLoaderDaemon.loadImagesTo(me,imageListSource)
The imageLoaderDaemon is created and sent a "loadImagesTo" message where we specify what object the Daemon should try and load images into. We also specify the URL that it uses to collect the list of images.
The "loadImagesTo" method of the imageLoaderDaemon looks like this:
on loadImagesTo (me, theTargetObject, URL)
myTarget = theTargetObject
-- query the url for the list of files
netOp = script("NetOP.GetText").new(URL)
netOp.addListener(me)
end
Basically, all that happens here is the imageLoaderDaemon keeps a reference to the object it will load images into, and then it starts a GetNetText operation to get the list of images.
Once the imageLoaderDaemon has this list, it then loops through the list preloading each image using a "NetOp.Preloader" object (discussed in the Preloading tutorial). This preloader object will report the status of the preload back to the imageLoaderDaemon, so the imageLoaderDaemon will use a ProgressBar widget to draw a progress bar into the tile. Once the image has been fully downloaded, the imageLoaderDaemon then inserts the image into the slider object, and starts downloading the next image in the list.
Here is the full HorizontalImageSlider.Behaviour script:
HorizontalImageSlider.Behaviour
property ancestor
property myMidH, myShift, myAlpha, myOffset
property myTrackingFlag, myStartH
property mySlideLeftRect, mySlideRightRect
on beginSprite me
thisSprite = sprite(me.spriteNum)
thisRect = thisSprite.rect
thisMember = thisSprite.member
thisCanvas = thisMember.image
thisCanvas.fill(thisCanvas.rect, rgb("#000000"))
--
myOffset = point(thisRect.left, thisRect.top)
myMidH = thisSprite.left + (thisSprite.width/2)
-- create the slider object
ancestor = script("HorizontalImageSlider.Class").new()
me.Initialise(thisCanvas, thisCanvas.rect)
-- create an Object to load up the images
-- #### CHANGE THIS TO YOUR SERVER ADDRESS ####
imageListSource = "http://vs4/GetImageList?"
imageLoaderDaemon = script("ImageLoader.NET").new()
imageLoaderDaemon.loadImagesTo(me,imageListSource)
-- create the 'hot spots' for sliding
mySlideLeftRect = rect(thisSprite.left, thisSprite.top,
thisSprite.left + (thisSprite.width/3), thisSprite.bottom)
mySlideRightRect = rect(thisSprite.right-(thisSprite.width/3),
thisSprite.top, thisSprite.right, thisSprite.bottom)
end
on endSprite (me)
-- clean up the canvas
thisSprite = sprite(me.spriteNum)
thisMember = thisSprite.member
thisCanvas = thisMember.image
thisCanvas.fill(thisCanvas.rect, rgb("#000000"))
end
on enterframe (me)
if myTrackingFlag then
-- the mouse was clicked on this sprite
if not (the mouseDown) then
-- stop tracking
myTrackingFlag = 0
else
-- 'drag' the slider to the current mouse location
mH = the mouseH
amt = myStartH - mH
myStartH = mH
me.Slide(amt)
end if
else
p = the mouseLoc
if inside(p, mySlideLeftRect) then
proposedAmt = myShift -1
myShift = Max(-10, proposedAmt)
else if inside(p, mySlideRightRect) then
proposedAmt = myShift + 1
myShift = Min(10, proposedAmt)
else
-- slow down to a stop
myShift = myShift * 0.75
if abs(myShift) < 2 then myShift = 0
end if
me.Slide(myShift)
end if
on mouseDown (me)
ClickedTile = me.GetTileIDAtPoint(the mouseLoc - myOffset)
if voidP(ClickedTile) then return
myTrackingFlag = 1
myShift= 0
myStartH = the mouseH
me.SelectTileByID(ClickedTile, (the shiftDown))
sendAllSprites(#ImageSelected, ClickedTile)
end
The 'imageLoaderDaemon' script is detailed next. It uses the "NetOP.GetText" script discussed elsewhere to ask the server for a list of images. Once it has the list, it loops through the list and downloads each image:
-- loads images from a remote directory (for shockwave)
property myTempBitmap, mySlider, myIndx, myImagesToLoad
property myTarget
property myProgressBarObj
on new (me)
myTempBitmap = member("ImageLoader.net.bitmap")
if myTempBitmap.type <> #bitmap then
myTempBitmap = new(#bitmap)
myTempBitmap.name = "ImageLoader.net.bitmap"
end if
return me
end
on Destroy (me)
-- erase the bitmap
if myTempBitmap.ilk = #member then erase myTempBitmap
-- void our reference to the slider
myTarget = VOID
end
on stopMovie (me)
-- will get this message if the timeout is active
me.Destroy()
end
on loadImagesTo (me, theTargetObject, URL)
myTarget = theTargetObject
-- query the url for the list of files
netOp = script("NetOP.GetText").new(URL)
netOp.addListener(me)
end
-- messages sent by the getText netOP
on LoadNetText (me, netOp, args)
if args.error = 0 then
-- set what the server returned
imageFiles = value(args.text)
if imageFiles.ilk = #List then
-- we successfully interepretted it as a lingo list
-- now load some temporary images into the slider
myImagesToLoad = [:]
repeat with aFilePath in imageFiles
myImagesToLoad.addProp(aFilePath, member("SliderLoadingImage").image)
end repeat
myTarget.LoadImages(myImagesToLoad)
-- now start loading the real images
myIndx = 0
me._LoadNextImage()
else
alert "Error getting file list - received a " & imageFiles.ilk
end if
end if
end
-- messages sent by the preloader
on PreloadStatusUpdate (me, netOp, statusList)
-- this is sent by the preloader object. We will use the information
-- to animate a progress bar widget
if statusList.state = "InProgress" then
myProgressBarObj.ShowProgress(statusList.fractionDone)
else myProgressBarObj.ShowWorking()
end
on PreloadFinished (me, netOp, errorNum)
if errorNum <> 0 then
-- get a description of the error
description = netOp.GetErrorDescription()
netOp.Destroy()
alert "Network Error!" & return & description
else
whichFile = netOp.URL
myTempBitmap.filename = whichFile
-- replace the 'loading' image with the real one
myTarget.UpdateImage(myTempBitmap.image, whichFile)
netOp.Destroy()
-- now preload the next
me._LoadNextImage()
end if
end
------------
on _LoadNextImage (me)
if myIndx < myImagesToLoad.count then
-- still more images to preload.
myIndx = myIndx + 1
whichFile = myImagesToLoad.getPropAt(myIndx)
netop = script("NetOp.Preloader").new(whichFile)
netop.addListener(me)
myTileCurrentlyLoading = myTarget.GetTile(whichFile)
myProgressBarObj = script("Widget.ProgressBar").new()
myProgressBarObj.Initialise(myTileCurrentlyLoading.image, rect(5,20,80,28))
-- put "Loading " & whichFile
else
-- put "All Done"
end if
end