Panning a large graphic
July 27, 1998
by Pat McClellan
Dear Multimedia Handyman,
Is there a way I can have a panorama which is larger in width than the stage, pan left or right, up or down depending on the direction and velocity of the mouse (similar to QTVR)?
savva / at / savva.com.au
Dear Savva,
Seems like it should be easy, but it's a bit complicated. I guess that's why most people simply opt for using QTVR or one of the other VR options. But, I like a challenge (when I have time to deal with it) so here goes!
The behavior we write should have the following attributes:
- When you mouseDown and move the mouse, the graphic should move in the opposite direction (simulating a mouseward change in your perspective.)
- The further you move the mouse from your original click point, the faster the graphic should move.
- When you mouseUp or move the mouse off the graphic (stage), the motion should stop. Reclicking on the graphic (stage) will be necessary to restart it. (This is a necessity for Shockwave; otherwise, a mouseUp outside the stage is not sensed and the motion would continue.)
- Press the control key to zoom in.
- Press the command key to zoom out. (Note: This only works on the Mac, because the command key is seen as the control key on Windows. I'm don't know another option for Windows. I use controlDown and commandDown because they can continually be monitored. Without Brian Gray's KeyPoll xtra, there's not a good way to use standard keys.)
- The motion and/or zooming should stop if the image reaches the edge of the stage so you can't see beyond the graphic. (Note: in Shockwave, the left and top borders don't seem to work dependably. I suspect this has to do with the browser interferring with the stageLeft and stageTop properties. It works perfectly in a projector.)
- When you reach the edge of the graphic (and it stops moving) the "startPoint" for the mouse should reset so that as soon as you start moving the mouse the other way, the graphic resumes motion.
An additional feature might be to add hotspots to the graphic. However, that's considerably more complicated so I'll leave that for a future article.
Position can either be altered by setting locH and locV properties, or by altering the rect. Scaling can be altered by setting the height and width properties, or by altering the rect. Since both can be simultaneously set by altering the rect, I opted to use this approach. Using the rect also makes it easy to check the limits of the graphic vis a vis the stage.
One way to approach updating the image properties would be to do it in a repeat loop while the mouse is stillDown. Due to the often discussed problems with using repeat loops (other events are locked out), I decided to use an alternative approach: I use a flag to indicate when the mouse is down or up, and then update on each exitFrame.
In our beginSprite handler, we'll need to set some basic properties: our sprite number, the "speed", the mouseFlag I mentioned, an updateFlag which tells us if the new position for the rect is inside the limits of the stage, and a scale factor. These properties should become more obvious as we proceed into the rest of the code. property pSpeed, mySprite, pStartMouse, pMouseFlag, pUpdateFlag, pDeltaRect, pScaleFactor
on beginSprite me set pSpeed = 20 set mySprite = the spriteNum of me set pMouseFlag = 0 set pUpdateFlag = FALSE set pDeltaRect = rect(0,0,0,0) set pScaleFactor = 1.00 endWhen the mouse is clicked (down), all that happens is that our mouseFlag is set to 1 and the initial position of the mouse is set into our pStartMouse property. On mouseUp, the mouseFlag is turned off.
on mouseDown me set pStartMouse = point(the mouseH, the mouseV) set pMouseFlag = 1 end on mouseUp me set pMouseFlag = 0 endAs the movie exits each frame, we'll want to first check to assure that the mouse is still over the graphic (stage). If so, then we'll proceed with calculating the position and the scale factor. I've separated these operations into distinct handlers below. Another handler "checkLimits", takes the newly calculated rect and tests to assure that it is within the limits of our stage. If so, the updateFlag is set to TRUE. Back in our exitFrame handler, if the updateFlag is TRUE, then the sprite's current rect is altered by deltaRect (the change calculated in the setPosition handler), and the resulting rect is scaled by the pScaleFactor set in the setScale handler.
on exitFrame me
if rollOver(mySprite) then
setScale me
setPosition me
checkLimits me
if pUpdateFlag then
set currentRect = the rect of ¬
sprite mySprite
set newRect = (currentRect + ¬
pDeltaRect) * pScaleFactor
set the rect of sprite mySprite = newRect
else
set pStartMouse = point(the mouseH,¬
the mouseV)
end if
else
set pMouseFlag = 0
end if
end
on setScale me
if the controlDown then
set pScaleFactor = 1.01
else if the commandDown then
set pScaleFactor = 0.99
else
set pScaleFactor = 1.00
end if
end
on setPosition me
if pMouseFlag = 1 then
set currentMouse = point(the mouseH, ¬
the mouseV)
set deltaMouse = pStartMouse - currentMouse
set deltaH = getAt (deltaMouse,1)/pSpeed
set deltaV = getAt (deltaMouse,2)/pSpeed
set pDeltaRect = rect(deltaH,deltaV,¬
deltaH, deltaV)
else
set pDeltaRect = rect(0,0,0,0)
end if
end
on checkLimits me
set currentRect = the rect of sprite mySprite
set testRect = (currentRect + pDeltaRect) ¬
* pScaleFactor
if (the right of testRect > the stageRight) ¬
AND (the left of testRect < the stageLeft) ¬
AND (the top of testRect < the stageTop)¬
AND (the bottom of testRect > the ¬
stageBottom) then
set pUpdateFlag = TRUE
else
set pUpdateFlag = FALSE
end if
end
I hope this behavior will get you started. There are many modifications and additions which could enhance the functionality of the behavior. I might suggest changing cursors based on the direction of the mouse motion from the startMouse loc. Good luck with your program.
Copyright 1997-2025, Director Online. Article content copyright by respective authors.