mrhat557
mrhat557

Reputation: 1

XML image slider - loop?

I've created a image slideshow with xml-driven images that slide to the right automatically, or with next and previous buttons. I currently have it set up to rewind to the beginning of the image sequence with a scripted tween after the last image using setInterval. I now need to change this functionality so the sequence is a continuous loop (in other words, when you click the next button on the last image, the first image slides in as the next image, instead of it rewinding back to the first image). I have posted my code below. I would be extremely grateful if somebody would be kind enough to help me figure this out.

Thanks!

import mx.transitions.Tween;
import mx.transitions.easing.*;
//-------------------------------
// Load XML
var adBanner_xml:XML = new XML ();
adBanner_xml.ignoreWhite = true;
adBanner_xml.load ("adBanner.xml");
adBanner_xml.onLoad = function (success:Boolean) {
    if (success) {
        trace ("XML loaded successfully!");
        trace ("-------------------------------------------------------");
        var adBanner = adBanner_xml.firstChild;
        var adsLength = adBanner.childNodes.length;
        trace (adsLength);
        buildAd (adsLength);
    }
    else {
        trace ("XML not loaded!");
    }
};
//---------------------------------------
// Variables
var maskWidth:Number = _root.contain_mc.adBanner_mc.adMask_mc._width;
var curPos:Number = _root.contain_mc.adBanner_mc.adImages_mc._x;
var newPos:Number;
//the higher the slower
var lengthOfTime:Number = 1;
var adArray:Array = new Array ();
var adLocation:Number = 0;
var adsLength:Number;
// TIMER VAR
var adInterval:Number;
//in milliseconds
var duration:Number = 6000;
//-------------------------------------------
// insert ad images and copy into adImages_mc
function buildAd (numberOfAds:Number) {
    adsLength = numberOfAds;

    for (var i:Number = 0; i < numberOfAds; i++) {
        var adName:String = "ad" + i + "_mc";
        adArray.push (adName);
        var prevAd:MovieClip = adArray[i - 1];

        _root.contain_mc.adBanner_mc.adImages_mc.ad_mc._visible = false;
        _root.contain_mc.adBanner_mc.adImages_mc.ad_mc.duplicateMovieClip (adName, i);
        _root.contain_mc.adBanner_mc.adImages_mc[adName]._x = i * 780;
        //-----------------
        // Insert xml values
        _root.contain_mc.adBanner_mc.adImages_mc[adName].adTitle_txt.text = adBanner_xml.firstChild.childNodes[i].childNodes[0].firstChild;
        _root.contain_mc.adBanner_mc.adImages_mc[adName].adDesc_txt.text = adBanner_xml.firstChild.childNodes[i].childNodes[1].firstChild;
        _root.contain_mc.adBanner_mc.adImages_mc[adName].adPrice_txt.text = adBanner_xml.firstChild.childNodes[i].childNodes[2].firstChild;
        _root.contain_mc.adBanner_mc.adImages_mc[adName].imgPH_mc.loadMovie (adBanner_xml.firstChild.childNodes[i].attributes.imgPath, i);
        //------------------
        _root.contain_mc.adBanner_mc.adImages_mc[adName].adID = i;
        //
    }
    //
    startInterval ();
}
//-------------------------------------------------------
// Move ad
function adMovement (adLocation) {
    adLocation = adLocation;
    clearInterval (adInterval);
    newPos = -(maskWidth * adLocation);
    // (Movie clip to be tweened, property of movieclip to change, type of easing, begin position, end position, duration of tween, use seconds(true) or frames(false);
    var tween_handler:Object = new Tween (_root.contain_mc.adBanner_mc.adImages_mc, "_x", Strong.easeOut, curPos, newPos, lengthOfTime, true);
    curPos = newPos;
    startInterval ();
}
//---------------------------------------------
// Arrow hit functions
_root.contain_mc.adBanner_mc.navArrows_mc.arrowLeft_mc.hit_btn.onRelease = function () {
    if (adLocation != 0) {
        adLocation--;
        adMovement (adLocation);
    }
};
_root.contain_mc.adBanner_mc.navArrows_mc.arrowRight_mc.hit_btn.onRelease = function () {
    if (adLocation < (adsLength-1)) {
        adLocation++;
        adMovement (adLocation);
    }
};
//-----------------------------------------------
// TIMER 
function rotateTimer ():Void {
    if (adLocation >= (adsLength - 1)) {
        //adCount = 0;
        adMovement (0);
        adLocation = 0;
    }
    else {
        adLocation++;
        adMovement (adLocation);
    }
}
//-----
function startInterval ():Void {
    adInterval = setInterval (rotateTimer, duration);
}
//----------------------------------------------
// Order Now button
function orderNow (adID) {
    var path:String = adBanner_xml.firstChild.childNodes[adID].attributes.linkPath;
    getURL (path);
}

Upvotes: 0

Views: 977

Answers (2)

gthmb
gthmb

Reputation: 808

I assume you already have the loading the images from your XML file taken care of, and have this in place:

  • a containing clip for all your images, that has all your images in a lined up inside of it.
  • a mask that will be your 'viewport' applied to your container (only allows a section of the container to be viewed)
  • some mechanism to trigger next/prev logic that slides your container underneath your mask

^ sounds like you are to this point.

What you need to add is logic to adjust the placement of the the images inside your container as the user navigates forward/backward.

.... went off to find my old code ....

here is an example (AS3):

import fl.transitions.Tween;
import fl.transitions.easing.Strong;

// index in theItems of the currently viewed image
var curIndex = 0;

// boolean to track if the container is moving forward (left) or backward (right)
var movingForward:Boolean = false

// an array of the itmes (images) in the container
var theItems = [ container.item1, container.item2, container.item3, container.item4 ];

// add listeners to the next/prev buttons
nextBtn.addEventListener( MouseEvent.CLICK, showNext );
prevBtn.addEventListener( MouseEvent.CLICK, showPrev );

// stores direction, replaces items, updates current index and tells the container where to move
function showNext( e:MouseEvent = null ) : void
{
    movingForward = true;
    placeItemsForLooping( getNextIndex() ); // look an item ahead and make sure its in the right position
    curIndex = getNextIndex();
    showItem( curIndex );
}

// stores direction, replaces items, updates current index and tells the container where to move
function showPrev( e:MouseEvent = null ) : void
{
    movingForward = false;
    placeItemsForLooping( getPrevIndex() ); // look an item ahead and make sure its in the right position
    curIndex = getPrevIndex();
    showItem( curIndex );
}

// figures out the distance that the container needs to move to align the desired item under the mask and tweens it
function showItem( itemIndex:int )
{
    var showMe:MovieClip = theItems[itemIndex];     
    var showMeBounds:Rectangle = showMe.getRect( this.stage );
    var maskBounds:Rectangle = theMask.getRect( this.stage );
    var xDiff:int = showMeBounds.x - maskBounds.x - (theMask.width-showMe.width)/2;

    new Tween( container, 'x', Strong.easeOut, container.x, container.x - xDiff, 1, true );
}

// inspects position of desired item, and determines if it should be moved based on the current direction
function placeItemsForLooping( itemIndex:int )
{
    var nextItem:DisplayObject = theItems[itemIndex];
    var nextBounds:Rectangle = nextItem.getRect( theMask );
    var containerBounds:Rectangle = container.getBounds(container);

    if( movingForward )
    {
        if( nextBounds.x < 0 ) nextItem.x = containerBounds.right;
    }
    else
    {
        if( nextBounds.x > 0 ) nextItem.x = containerBounds.left - nextItem.width;
    }
}

// the index of the item ahead of the currently viewed item
function getNextIndex():int
{
    return ( curIndex < theItems.length - 1) ? curIndex+1 : 0;
}

// the index of the item behind of the currently viewed item
function getPrevIndex():int
{
    return ( curIndex > 0) ? curIndex-1 : theItems.length-1;
}

went a little overboard. had to simplify some of my old code... sheesh, spent more time on this that i thought i would :)

example FLA: loopingDemo.fla

UPDATE (in AS2)

import mx.transitions.Tween;
import mx.transitions.easing.Strong;

// index in theItems of the currently viewed image
var curIndex = 0;

// boolean to track if the container is moving forward (left) or backward (right)
var movingForward:Boolean = false

// an array of the itmes (images) in the container
var theItems = [ container.item1, container.item2, container.item3, container.item4 ];

// add listeners to the next/prev buttons
nextBtn.onRelease = showNext;
prevBtn.onRelease = showPrev;

// stores direction, replaces items, updates current index and tells the container where to move
function showNext() : Void
{
    movingForward = true;
    placeItemsForLooping( getNextIndex() ); // look an item ahead and make sure its in the right position
    curIndex = getNextIndex();
    showItem( curIndex );
}

// stores direction, replaces items, updates current index and tells the container where to move
function showPrev() : Void
{
    movingForward = false;
    placeItemsForLooping( getPrevIndex() ); // look an item ahead and make sure its in the right position
    curIndex = getPrevIndex();
    showItem( curIndex );
}

// figures out the distance that the container needs to move to align the desired item under the mask and tweens it
function showItem( itemIndex:Number ) : Void
{
    var showMe:MovieClip = theItems[itemIndex];     
    var showMeBounds:Object = showMe.getBounds( _root );
    var maskBounds:Object = theMask.getBounds( _root );
    var xDiff:Number = showMeBounds.xMin - maskBounds.xMin - (theMask._width-showMe._width)/2;

    new Tween( container, '_x', Strong.easeOut, container._x, container._x - xDiff, 1, true );
}

// inspects position of desired item, and determines if it should be moved based on the current direction
function placeItemsForLooping( itemIndex:Number ) : Void
{
    var nextItem:MovieClip = theItems[itemIndex];
    var nextBounds:Object = nextItem.getBounds( theMask );
    var containerBounds:Object = container.getBounds(container);

    if( movingForward )
    {
        if( nextBounds.xMin < 0 ) nextItem._x = containerBounds.xMax
    }
    else
    {
        if( nextBounds.xMin > 0 ) nextItem._x = containerBounds.xMin - nextItem._width;
    }
}

// the index of the item ahead of the currently viewed item
function getNextIndex():Number
{
    return ( curIndex < theItems.length - 1) ? curIndex+1 : 0;
}

// the index of the item behind of the currently viewed item
function getPrevIndex():Number
{
    return ( curIndex > 0) ? curIndex-1 : theItems.length-1;
}

example AS2 FLA: loopingDemoAS2.fla.zip

Upvotes: 0

exoboy
exoboy

Reputation: 2058

I don't have time to code this, but I can tell you how I have always done it...

Let's say that your display area holds thumbnails for 10 images.

What I normally do is a little visual trickery:

First, I create the SWF containing all of the thumbnails that the user is allowed the "scroll" through.

Next, I add copies of the first 10 thumbnails (which is the smallest number of thumbnails images viewable in our viewing SWF) to the END of my chain of thumbnail images.

The user can now scroll through all of the thumbnail images without any trailing blank space appearing in the thumbnail browsing SWF.

Then, I once the user scrolls the last item out of view (not one of the original 10, but the last one in the original set of thumbs, minus the first ten), they should now be looking at your original 10 thumbnails (which are actually the last 10 in the SWF).

Then, I simply move the entire SWF that holds all of your thumbnail images BACK to its starting point.

That way, you have actually just re-wound your scrolling list of thumbnails, but the user will perceive it as an endless, or wrap-around loop of images.

That is the basic logic anyway.

Hope his helps!

Upvotes: 1

Related Questions