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).

View Demo | Download Source

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.

Diagram of interacting objects Main objects involved in retrieving a list of images, preloading them and then loading the images into the slider

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
First published 24/06/2005