1

I'm making an image gallery and I want to have a bunch of thumbnails on the bottom of the screen that smoothly slide from side to side when the mouse moves.

I'm working with a custom class for the container (Tiles) and a custom class for the thumbnails (ImageIcon).

I have a ComboBox which allows users to to choose a gallery. When the user chooses a gallery, the following code is run and the thumbnails should reload. The problem here is that the icons appear on top of each other instead of side by side, also switching categories should remove the old one (see the first for loop), but it does not. Also, the Icons are not animating properly. The animation code is below as well. Right now, only one of the icons will move. The icons should move in order from side to side, stopping when the last few icons hit the edge of the screen, so that they don't get "lost" somewhere off to the side.

Gallery Loader Code:

public function loadCategory(xml:XML = null) {
    if (xml != null) {
        dp = new DataProvider(xml);
        for (var k:int = 0; k < this.numChildren; k++) {
            this.removeChild(this.getChildAt(k));
        }

        var black:DropShadowFilter = new DropShadowFilter(0, 45, 0x000000, 1, 3, 3, 1, 1);
        var white:DropShadowFilter = new DropShadowFilter(0, 45, 0xFFFFFF, 1, 2, 2, 1, 1);

        for (var i:int = 0; i < dp.length; i++) {
            var imgicon:ImageIcon = new ImageIcon();
            imgicon.addEventListener(MouseEvent.CLICK, showImage);
            imgicon.width = 100;
            imgicon.x = (i * (imgicon.width + 20));
            imgicon.path = dp.getItemAt(i).data;
            imgicon.loadIcon();
            imgicon.filters = [black, white];

            stage.addEventListener(Event.ENTER_FRAME, moveIcon);
            this.addChild(imgicon);
        }
    } else {
        //Failed to load XML
    }
}

Icon Animation Code:

public function moveIcon(e:Event){
    var speed = 0;
    speed = Math.floor(Math.abs(this.mouseX/20));

    var image = this.getChildAt(k);

    var imagebox = image.width + 20;

    var edge:Number = (800/2);

    if (this.mouseX > 0) {
        for (var k:int = 0; k < this.numChildren; k++) {
            if (image.x - (imagebox/2) + speed < -edge + (k * imagebox)) {
                speed = 0;
            }

            image.rotationY = Math.floor(image.x/20);
            image.x -= Math.floor(speed);
        }
    } else {
        for (var j = this.numChildren; j >= 0; j--) {
            if (image.x + speed > edge - ((imagebox * j) )) {
                speed = 0;
            }

            image.rotationY = Math.floor(image.x/20);
            image.x += Math.floor(speed);
        }
    }
}
gevorg
  • 4,835
  • 4
  • 35
  • 52
Moshe
  • 57,511
  • 78
  • 272
  • 425

1 Answers1

2

As I see it, you have three questions (You should have put these at the end of your question instead of "What is wrong with my code?"). One of the main principles of programming is breaking problems into smaller parts.

  1. How do I line up the ImageIcon beside each other?
  2. How do I remove the old ImageIcon, when switching categories?
  3. How do I animate ALL the ImageIcons together, based on the mouse position, with constraints on either side?

Question 1

I can't see anything wrong, but just check that when you are setting imgicon.x, that imgicon.width is actually set.

Question 2

Instead of relying on numChildren and getChildAt(), I would create a currentIcons array member variable, and when you create a new ImageIcon, just push it onto the array. Then when you want to remove them, you can just loop through the array like this:

for each (var cIcon:ImageIcon in currentIcons) 
{
    cIcon.removeEventListener(MouseEvent.CLICK, showImage);
    removeChild(cIcon);
}
currentIcons = [];

As you can see, I am also removing any listeners that I have added. This is best practice. Then clearing the array when I have removed all the icons.

Question 3

I can see a few things wrong with your code. First, in the line where image is set, k is not set yet!

Here you can also use the currentIcons array, but you probably can't use a for each in loop, because that gives you the items out of order. Just a normal for loop will be better.

I haven't tested this code for the moveIcon method, but the idea should work. You may have to tweek it though:

public function moveIcon(e:Event):void 
{
    var speed:Number = Math.floor(this.mouseX / 20); // Removed "abs".
    var imageBox:Number = currentIcons[0].width;
    var edge:Number = 800 / 2;

    for (var i:int = 0; i < currentIcons.length; i++) 
    {
        var image:ImageIcon = currentIcons[i] as ImageIcon;
        image.x += speed;
        image.rotationY = Math.floor(image.x / 20);

        var min:int = -edge + (i * imagebox);
        if (image.x < min) image.x = min;

        var max:int = edge - (imagebox * i);
        if (image.x > max) image.x = max;
    }
}

EDIT* Sorry, it was supposed to be a greater than in the last if statement, but I had a less than by accident.

Adam Harte
  • 10,369
  • 7
  • 52
  • 85
  • 1
    Plus one for a thorough answer. I have to test this to see if it's working, but it looks right. I have done this before, but I lost my source code. (It was a year ago - I've been through several machines/OSs since.) – Moshe Nov 16 '10 at 20:17
  • The array works wonders, but the images are starting off to the right of the screen now! – Moshe Nov 16 '10 at 20:55
  • @TandemAdam - I fixed that myself. Yea that was it. – Moshe Nov 17 '10 at 01:40
  • But what happens if there are more images on the screen than there is room to show them? – Moshe Nov 17 '10 at 01:41
  • Also, your code makes the icons jump. I'd reset speed to 0 before applying it. – Moshe Nov 17 '10 at 01:42
  • Okay, two more comments: `imagebox` should be `imageBox`. Also, one-line if statements make it hard to refactor. – Moshe Nov 17 '10 at 01:44
  • Selected since this led me to having working code. The array was the main point here. – Moshe Nov 17 '10 at 02:51