Skip navigation
Currently Being Moderated

Next previous button in gallery

Aug 14, 2012 2:42 PM

Hi guys, been a while, hope everyone is well.  I am having a problem implementing a next/previous button on an image once it has been enlarged in my gallery.  I have done it in pure as3 but all tutorials seem to use the timeline.  I will post my code underneath so you can see what I am up too.  The next/previous button should I think be added to the modelClicked function.

 

From what I understand, I will get a next/previous button and turn them into a button object.  I will then delete them from my stage and instantiate them within the class below.  I would then add them to the modelClicked function with events tied to them.  What should I then do in these events to make it fit in with the code below?

 

Any advise appreciated,

 

Cheers

 

Nick

 

 

package classes.models
{

    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.geom.Rectangle;

    import flash.events.MouseEvent;
    import flash.events.Event;

    import flash.net.URLRequest;

    import eu.flashlabs.ui.BasicButton;

    import classes.ui.StateClip;
    import classes.ui.Placeholder;

    import classes.utils.URLUtil;

    import classes.vo.ModelsStates;

    import fl.containers.ScrollPane;
    import fl.controls.ProgressBar;

    import com.greensock.TweenLite;


    public class IndividualModel extends StateClip
    {

        //--------------------------------------------------------------------------
        // CONSTANTS
        //--------------------------------------------------------------------------

        private static const PADDING_TOP:Number= 28;
        private static const PADDING_LEFT:Number= 50;
        private static const COLS:int= 4;
        private static const ROWS:int= 8;
        private static const GAP_HORIZONTAL:Number= 5;
        private static const GAP_VERTICAL:Number= 5;

        //--------------------------------------------------------------------------
        // MEMBER VARIABLES
        //--------------------------------------------------------------------------

        private var _data:XML;
        public function get data():XML
        {
            return _data;
        }
        public function set data(value:XML):void
        {
            setData(value);
        }

        private var items:Array;

        private var backBtn:BasicButton;

        private var itemsHolder:MovieClip;

        private var loadIndex:int;

        private var sp:ScrollPane;

        private var clonedBitmap:Bitmap;
        private var originalBitmap:Bitmap;
        private var rect:Rectangle;

        private var screen:Sprite = new Sprite();

        public function IndividualModel()
        {
            super();
            items = [];
            
            addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }
        
        private function addedToStageHandler(event:Event):void
        {
            initChildren();
        }

        private function initChildren():void
        {
            itemsHolder = new MovieClip();
            addChild(itemsHolder);

            sp = getChildByName("mc_pane") as ScrollPane;

            backBtn = getChildByName("btn_back") as BasicButton;
            backBtn.addEventListener(MouseEvent.CLICK, backBtn_clickHandler);

            screen.graphics.beginFill(0x111111, .75);
            screen.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            screen.graphics.endFill();
        }

        public function destroy():void
        {
            clearItems();
        }

        //--------------------------------------------------------------------------
        // PUBLIC INTERFACE
        //--------------------------------------------------------------------------

        //--------------------------------------------------------------------------
        // LAYOUT
        //--------------------------------------------------------------------------

        private function clearItems():void
        {
            while (items.length > 0)
            {
                var item:ModelsItem = items.pop() as ModelsItem;
                itemsHolder.removeChild(item);
                item.destroy();
            }
        }

        private function populateItems():void
        {
            for (var i:int = 0; i < Math.min(COLS * ROWS, data.picture.length()); i++)
            {
                var item:ModelsItem = new ModelsItem();
                item.data = data.picture[i];
                item.x = PADDING_LEFT + (i % COLS) * (ModelsItem.ITEM_WIDTH + GAP_HORIZONTAL);
                item.y = PADDING_TOP + Math.floor(i / COLS) * (ModelsItem.ITEM_HEIGHT + GAP_VERTICAL);
                /*item.addEventListener(MouseEvent.CLICK, modelClicked);*/
                itemsHolder.addChild(item);
                /*item.mouseEnabled = false;*/
                sp.source = itemsHolder;
                items.push(item);
            }
            sp.verticalScrollPolicy = "on";
            sp.horizontalScrollPolicy = "off";
            sp.update();
        }

        //--------------------------------------------------------------------------
        // PICTURE LOADING
        //--------------------------------------------------------------------------

        private function loadNextPicture():void
        {
            if (loadIndex < items.length)
            {
                var loader:Loader = new Loader();
                loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadNextPicture_completeHandler);
                var item:ModelsItem = items[loadIndex] as ModelsItem;
                loader.load(new URLRequest(URLUtil.getURL(item.data.@url.toString())));
                /*item.mouseEnabled = true;*/
            }
        }

        private function loadNextPicture_completeHandler(event:Event):void
        {
            event.target.removeEventListener(Event.COMPLETE, loadNextPicture_completeHandler);

            ModelsItem(items[loadIndex]).bitmap = event.target.content as Bitmap;
            ModelsItem(items[loadIndex]).addEventListener(MouseEvent.CLICK, modelClicked);
            
            loadIndex++;
            loadNextPicture();
        }

        //--------------------------------------------------------------------------
        // EVENT HANDLERS
        //--------------------------------------------------------------------------

        private function backBtn_clickHandler(event:MouseEvent):void
        {
            state = ModelsStates.HIDDEN;
        }

        private function modelClicked(e:MouseEvent):void
        {
            stage.addChild(screen);
            var item:ModelsItem = e.currentTarget as ModelsItem;
            originalBitmap = item.bitmap;
            clonedBitmap = new Bitmap(originalBitmap.bitmapData.clone());

            stage.addChild(clonedBitmap);

            rect = originalBitmap.getBounds(stage);
            clonedBitmap.x = rect.x;
            clonedBitmap.y = rect.y;
            clonedBitmap.width = rect.width;
            clonedBitmap.height = rect.height;
            clonedBitmap.smoothing = true;

            TweenLite.to(clonedBitmap, 1, { x: (stage.stageWidth - originalBitmap.width) / 4, y: (stage.stageHeight - originalBitmap.height) / 6, onComplete:zoomInFinished, scaleX: 1, scaleY: 1 });

        }

        private function zoomInFinished():void
        {
            trace("Zoom In Finished");
            stage.addEventListener(MouseEvent.CLICK, mouseClicked);
        }

        private function mouseClicked(e:MouseEvent):void
        {
            TweenLite.to(clonedBitmap, 1, { x: rect.x, y: rect.y, onComplete:zoomOutFinished, width: rect.width, height: rect.height});
            stage.removeEventListener(MouseEvent.CLICK, mouseClicked);
        }
        
        private function zoomOutFinished():void
        {
            trace("Mouse Clicked");
            stage.removeChild(screen);
            stage.removeChild(clonedBitmap);
        }
        
        //--------------------------------------------------------------------------
        // GETTERS & SETTERS
        //--------------------------------------------------------------------------

        private function setData(value:XML):void
        {
            _data = value;

            clearItems();
            populateItems();

            loadIndex = 0;
            loadNextPicture();

            state = ModelsStates.SHOWN;
        }

        //--------------------------------------------------------------------------
        // UTILS
        //--------------------------------------------------------------------------

        override protected function animateInComplete():void
        {
            super.animateInComplete();

            switch (state)
            {
                case ModelsStates.SHOWN :
                    break;
                case ModelsStates.HIDDEN :
                    break;
            }
        }

    }
}
 
Replies
  • Currently Being Moderated
    Aug 14, 2012 5:57 PM   in reply to nick2price

    No offense, but I lost interest about halfway through your code. It's just too much code to ask someone to go through and try to guess where your problem is.

     

    A few questions, maybe they'll help me zero in on your issue:

     

    1. What in your code is working and what isn't?
    2. In the part that isn't working, what are your trace statements or debugger telling you?
    3. Why do you want to delete the instances off the stage and then move them to something you created entirely in AS? Do you feel like the stage is "dirty"? Or do you not know how to reference stage objects and just use them as they are? Or something else?
    4. Why aren't you instantiating straight from the library if the stage bothers you so much?
    5. Your items appear to be serving as data sources in your load next image function, but you're adding them to the stage. What's up with that? Are they models or are they views?
     
    |
    Mark as:
  • Currently Being Moderated
    Aug 15, 2012 5:36 PM   in reply to nick2price

    You'd have access to it in the code whether you delete it or not, or whether you put it on the stage or instantiate it directly from the library. What are you specifically having an issue with?

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 18, 2012 7:29 AM   in reply to nick2price

    Divide the current function into two functions. In the first function, just find the index of the item in your items list, then call the second function. In the second function, find the item in the items list from its index and then run the code on it just like you are now.

     

    Now, you can use your second function from your next and previous buttons. They will simply increment or decrement from a stored current index variable and call the new function that can enlarge the item based on index.

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 19, 2012 9:51 AM   in reply to nick2price

    I don't actually know how you're loading your data.  It's also very difficult to figure out what's happening in your code, since you're extending Classes you don't show. What I can tell you is that you need to store the data about iterating each collection at the level where it's needed. You may want to look at the composite pattern http://www.as3dp.com/2007/05/composite-pattern-book-part-1/ .

     

    In my opinion, the biggest problem you have is poor separation of concerns--you call things Models that are clearly Views, and because you are storing relevant data in Views rather than simply using your Views to represent data, you're making the task of representing and iterating through your data much harder than it needs to be.

     

    The ideal structure would be a data structure that has data for each thumbnail in some sort of collection, like an Array or Vector. This data structure would only be responsible for storing the data and maintaining a pointer to the currently selected thumbnail.  When the pointer changes, the data object dispatches a change event, so Views that care about this pointer can update. Each piece of data could then have a member variable that is one of these collections that manages the correct pointer.  That's where the composite pattern comes in.

     

    Now, the task of building your Views becomes much easier. You have one View that gets a collection and shows all the thumbnails and one View that gets a specific thumbnail, mix and match as needed. The Views, again watch the change event and do whatever they need to do when the pointer changes.

     

    At this point, who sets the pointer ceases to matter. It can be inside one of your Views or outside any of your Views--when the pointer changes, the View that is watching that particular collection will update, and if the result of that update is that a nested View then watches a different collection, that's ok--it still follows the same principles.

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points