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-2024, Director Online. Article content copyright by respective authors.