Articles Archive
Articles Search
Director Wiki

Image scroller

April 2, 2000
by Pat McClellan

Dear Multimedia Handyman,

I have an image which I created in Photoshop, but it is larger than the Director movie dimensions so some of it is off the stage. I have made a button which I want to be able to rollover and then this must slide the remaining image onto the stage. When you roll off the button, the image slides back to the original position. Hope you can help...


Dear Wesleigh,

I understand what you're describing, but let's get very specific in thinking about what the behavior needs to do. Let's assume that the left side of the image is at the left side of the stage, with a portion of the image extending off the right side of the stage. As you describe it, when the button is rolled over the image slides all the way in so that the right edge of the image as at the right side of the screen, and the image extends off the left side of the screen. And then when the user rolls off the button, the image returns to its original spot.

My concern is that it doesn't give the user the control to scroll just a little bit one way or the other. And while you might not want that to happen, when we're creating a behavior that we'll likely use in the future for other applications, it's best to build in that option. In your question, you don't say specifically whether the image is also taller than the stage. Again, for maximum flexibility and re-usability, we'll build the behavior so that it can work horizontally and vertically.

You suggest using a button to make the image slide, but a more intuitive solution might be to create a margin around the edge of the frame so that when the mouse gets within 15 pixels (for example) of the right edge, the image would scroll so you can see a bit more on the right. We'll call this feature "autoScroll", and make it optional; the author can either use autoScroll, or make the image scroll by calling the slide handlers from Lingo.

Here's a demo that shows what I've just described. Initially, you'll see that the Director Logo is flush-left. The autoScroll feature is turned on, so if you move the mouse within 15 pixels of the right edge of the stage, it will scroll. But you can stop it mid-scroll by pulling the cursor away from the edge. You can scroll it back to the left edge by putting the mouse within 15 pixels of the left edge. You can also scroll it up and down just a little.

D7 download for Mac or Windows.

Now click the next button. In this case, the autoScroll feature is turned off, so putting the cursor near the edge has no effect. Instead, you'll used those buttons (just rollover, not mouseDown) to scroll the image around. The button in the center will center the image horizontally and vertically.

Let's look at how it's done. When you drop the behavior on the sprite which will be scrolled, here are the options you'll have to choose from:

The Window Rect is the virtual window through which we are seeing the image scroll. So while our example uses the full stage (and that's the default for the behavior), you could set it up so that the image is scrolling within a smaller window. Next, we need to select the initial positioning of the image. I've built in options for flush left, flush right and center, and top, bottom and center for vertical justification.

Speed refers to how fast the image will slide. I selected 5 pixels per frame for the default speed. Trigger margin is only needed if you are also selecting the Auto Scroll feature. If autoScroll is off, then the trigger margin is ignored. In the first part of the demo above, I was using the default setting of 15 pixels. That means that when the mouse is within 15 pixels of the edges of the Window Rect, the command to slide one way or the other is given. And if the cursor is in the corner, commands to slide both horizontally and vertically are issued.

In the beginSprite handler, I set up some properties that we'll be needing throughout the behavior. These include pCenterH, pCenterV, pLeft, pRight, pTop and pBottom. These will be critical later, when we'll use them to determine whether to continue sliding or that we've reached the end of the slide. After setting the properties, the beginSprite handler sets the initial locH (left/right/center) and locV (top/bottom/center).

on beginSprite me
  pSprite = sprite(me.spriteNum)
  pNoTriggerRect = pWindowRect + rect(pTriggerMargin, pTriggerMargin, \
   -pTriggerMargin, -pTriggerMargin)
  pCenterH = (pWindowRect[3] * .5)
  pCenterV = (pWindowRect[4] * .5)
  slideHrange = pSprite.width - pWindowRect.width
  slideVrange = pSprite.height - pWindowRect.height
  pLeft = pCenterH + (slideHrange/2)
  pTop = pCenterV + (slideVrange/2)
  pRight = pCenterH - (slideHrange/2)
  pBottom = pCenterV - (slideVrange/2)
  case pJustifyH of
    #left: pSprite.locH = pLeft
    #center: pSprite.locH = pCenterH
    #right: pSprite.locH = pRight
  end case
  case pJustifyV of
    #top: pSprite.locV = pTop
    #center: pSprite.locV = pCenterV
    #bottom: pSprite.locV = pBottom
  end case
end beginSprite

To use the autoScroll feature, the exitFrame handler needs to check if autoScroll is on and also whether the mouse is both rolled over our scrolling image AND not inside of the noTriggerRect. I know that's a little convoluted, but you need to be clear on how this works. Take another look at the screenshot above if you're unclear. Here's the exitFrame handler:

on exitFrame me
  if pAutoScroll AND (rollOver(spriteNum)) then
    if NOT(inside(the mouseLoc, pNoTriggerRect)) then
      checkForSlide me
    end if
  end if

If autoScroll is selected, and the mouse is rolled over the image sprite, and the mouse is not inside the noTriggerRect, then we check to see if we should slide. Now, you're thinking "what do you mean 'check to see if we should slide?' Haven't we just checked?!" That's true, we know that it should slide, but we don't yet know which direction. Here's how we determine that:

on checkForSlide me
  if the mouseH < pWindowRect[1] + pTriggerMargin then
    slideRight me
  else if the mouseH > pWindowRect[3] - pTriggerMargin then
    slideLeft me
  end if
  if the mouseV < pWindowRect[2] + pTriggerMargin then
    slideDown me
  else if the mouseV > pWindowRect[4] - pTriggerMargin then
    slideUp me
  end if
end checkForSlide

This checkForSlide handler figures out which area the mouse is in and issues the command(s) to slide the appropriate direction. As long as the mouse stays in the trigger area, the checkForSlide handler is called on every exitFrame. So it does its evaluation and sends the command to slide on each exitFrame as well. That means that as soon as you roll the mouse outside of the trigger area, the commands stop and the image stops scrolling. This gives the user that control to scroll just a bit. Below are the individual handlers needed to scroll in a particular direction. They use the min and max functions to act as a switch. They will move the image pSpeed pixels in the appropriate direction -- up until the point where that location exceeds the limit of pLeft, pRight, pTop, pBottom, pCenterH or pCenterV. If you're not familiar with min and max functions, check them out in the Lingo dictionary. They're quite useful.

on slideRight me
  pSprite.locH = min(pLeft, pSprite.locH + pSpeed)
end slideRight

on slideLeft me
  pSprite.locH = max(pRight, pSprite.locH - pSpeed)
end slideLeft

on slideDown me
  pSprite.locV = min(pTop, pSprite.locV + pSpeed)
end slideDown

on slideUp me
  pSprite.locV = max(pBottom, pSprite.locV - pSpeed)
end slideUp

on slideCenterH me
  if pSprite.locH > pCenterH then
    pSprite.locH = max(pCenterH, pSprite.locH - pSpeed)
  else if pSprite.locH < pCenterH then
    pSprite.locH = min(pCenterH, pSprite.locH + pSpeed)
  end if
end slideCenterH

on slideCenterV me
  if pSprite.locV > pCenterV then
    pSprite.locV = max(pCenterV, pSprite.locV - pSpeed)
  else if pSprite.locV < pCenterV then
    pSprite.locV = min(pCenterV, pSprite.locV + pSpeed)
  end if
end slideCenterV

You may be wondering why I separated the slide commands out into the handlers immediately above. Four of them are only a single line of code, so why not put them into the checkForSlide handler? The reason is that we want to be able to call these handlers from outside the behavior. Remember, we have the option to turn autoScroll off and use buttons instead. I created a behavior to drop on the buttons that calls to the image sprite and tells it to #slideLeft, or one of the other directions. You can see that behavior in the download.

I hope this has given you an understanding of the methods needed to move a sprite around on command. If you understand the basics, you'll be able to adapt them to a variety of uses. Good luck with your project.

Patrick McClellan is Director Online's co-founder. Pat is Vice President, Managing Director for Jack Morton Worldwide, a global experiential marketing company. He is responsible for the San Francisco office, which helps major technology clients to develop marketing communications programs to reach enterprise and consumer audiences.

Copyright 1997-2019, Director Online. Article content copyright by respective authors.