Reset "Canvas" View

Hi there,
I’m currently working on a mapping tool which allows you to navigate around a map, zoom in and out, and then reset the view if required.
I’m having some problems with creating the reset view button which works up until you decide to zoom in. I have a feeling it has something to do with the scale of the image changing when you zoom in and the “reset scale” not being variable.

The entire code for the project is below (I have separated the “reset” code into a further code box below):


Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_MOVE,follow);
function follow(evt:MouseEvent){
 moveMapCursor.x = mouseX;
 moveMapCursor.y = mouseY;
}
 stage.addChild(moveMapCursor);
/*
ActionScript 3 Effect by Doug Ensley and Barbara Kaskosz.
http://www.flashandmath.com/
Last modified: May 26, 2010. 
*/
// Import the MatrixTransformer class
import fl.motion.MatrixTransformer;
/* 
Initially hide the zoom in/out cursors. Note that mcIn and mcOut were created on the stage and converted to movieclips using Modify > Convert to 
Symbol with the registration point set in the center. We converted the header text to a movieclip as well, mcHeader, to make it invisible while
the image is loading.
*/
mcIn.visible = false;
mcOut.visible = false;
mcCrosshair.visible = false;
mcHeader.visible=false;
but_reset.visible=false;
 
//We created a dynamic text field, infoBox, to display loading information.
infoBox.wordWrap=true;
infoBox.mouseEnabled=false;
// 'board' provides a background on which the image resides. 
var board:Sprite=new Sprite();
addChild(board);
// We create variables for the width and height of the board so we can scale the picture accordingly. 
//   These settings should be chosen with consideration of the pixel dimensions of the original picture.
var boardWidth:int=1024;
var boardHeight:int=720;
//The position of 'board' will detrmine the position of your picture within the main movie.
board.x=0;
board.y=75;
/* The board will have a background so we can have the whole board listen for mouse events. The "image sprite" created below will be a child of the board.
*/
board.graphics.beginFill(0xDDDDDD);
board.graphics.drawRect(0,0,boardWidth,boardHeight);
board.graphics.endFill();
/*
 spImage is a Sprite on which we will place the image. 
    spImage is a Sprite so we can attach listeners for response to mouse events to implement drag & drop.
*/
var spImage:Sprite = new Sprite();
board.addChild(spImage);
// Create a mask for the spImage with shape identical to the board. 
//   This will keep a scaled or moved picture from "leaving" the designated board area.
var boardMask:Shape=new Shape();
boardMask.graphics.beginFill(0xDDDDDD);
boardMask.graphics.drawRect(0,0,boardWidth,boardHeight);
boardMask.graphics.endFill();
boardMask.x = 0;
boardMask.y = 0;
board.addChild(boardMask);
spImage.mask = boardMask;
// scaleFactor for the proportion of scaling corresponding to each 'click' of the mouse wheel.
//   The value 0.8 reflects 80% scaling when zooming out and 125% scaling when zooming in.
var scaleFactor:Number = 0.3;
var minScale:Number = 0.25;
var maxScale:Number = 2.0;
var image:Bitmap;
// Declare variable for loading of image from a file.
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,initPic);
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,updateInfo);
infoBox.text="Loading begins";
//Replace Kazanie_Skargi by the name of your image or the address of your image.
loader.load(new URLRequest("HMOMap.jpg"));
function updateInfo(e:ProgressEvent):void {
 
 infoBox.text="Loading: "+String(Math.floor(e.bytesLoaded/1024))+" KB of "+String(Math.floor(e.bytesTotal/1024))+" KB.";
 
}
function initPic(e:Event):void {
 
 infoBox.text="";
 
 infoBox.visible=false;
 
 but_reset.visible=true;
 
 mcHeader.visible=true;
 
 image=Bitmap(loader.content);
 minScale = boardWidth/image.width;
 image.scaleX=minScale;
 image.scaleY=minScale;
 
 // We add the image and the cursor movie clips to spImage. Since spImage is masked, so will its children.
 spImage.addChild(image);
 spImage.addChild(mcIn);
 spImage.addChild(mcOut);
 spImage.addChild(mcCrosshair);
 
 /* 
 We use extremely basic drag and drop functionality. See the "Tour of Drag and Drop" tutorial on the flashandmath.com site for different models that allow for more flexibility.
 */
 spImage.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
 stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
 // Clean up listeners & loader now that the load is complete.
 loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,initPic);
 loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS,updateInfo);
 loader=null;
 // Drop shadows are always cool
 board.filters=[ new DropShadowFilter() ];
 
 // A click on the image sprite is handled by the zoom function below.
 spImage.addEventListener(MouseEvent.CLICK, zoom);
 
 
}
// Event handlers for mouse_down and mouse_up that enable basic drag-and-drop functionality.
function startDragging(mev:MouseEvent):void {
spImage.startDrag();
}
function stopDragging(mev:MouseEvent):void {
spImage.stopDrag();
}
// Event handler for click event that performs zooming in and out via MatrixTransformer methods.
function zoom(mev:MouseEvent):void {
 // If it is not the case that exactly one of the shift key or ctrl key is depressed, then we do nothing.
 if ((!mev.shiftKey)&&(!mev.ctrlKey)) {
  return;
 }
 if ((mev.shiftKey)&&(mev.ctrlKey)) {
  return;
 }
 
 // Declare a variable for the transform matrix of the image object.
 var mat:Matrix;
 
 /* 
 Get the point at the mouse in terms of image coordinates and (its parent) spImage coordinates. These points are aligned when the mouse click happens but after image is scaled, they will not be aligned anymore.
 */
 var externalCenter:Point=new Point(spImage.mouseX,spImage.mouseY);
 var internalCenter:Point=new Point(image.mouseX,image.mouseY);
 // We scaled the image up (but bounded by maxScale) or down (bounded by minScale) depending on whether the shift key
 //   or the ctrl key is down while the mouse click happens.
 if (mev.shiftKey) {
  image.scaleX = Math.max(scaleFactor*image.scaleX, minScale);
  image.scaleY = Math.max(scaleFactor*image.scaleY, minScale);
 }
 if (mev.ctrlKey) {
  image.scaleX = Math.min(1/scaleFactor*image.scaleX, maxScale);
  image.scaleY = Math.min(1/scaleFactor*image.scaleY, maxScale);
 }
 /* 
 The mat matrix is the transformation matrix for the scaled version of image; i.e., the version that no longer has internalCenter and external center aligned.
 */
 mat = image.transform.matrix.clone();
 /* 
 The matchInternalPointWithExternal method of the MatrixTransformer class changes the mat matrix to include a
 translation that makes the point in terms of image coordinates line up with the point in terms of spImage
 coordinates.
 */
 MatrixTransformer.matchInternalPointWithExternal(mat,internalCenter,externalCenter);
 // Now applying the mat matrix to the enlarged image will align the internalCenter to the externalCenter.
 image.transform.matrix=mat;
}
// We use the ctrl and shift keys to display the two different cursors that were created on the stage.
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyHandler);
function keyHandler(ke:KeyboardEvent):void {
 // No matter what key is pressed or released we move the cursor movie clips to the mouse position.
 mcIn.x = spImage.mouseX;
 mcIn.y = spImage.mouseY;
 mcOut.x = spImage.mouseX;
 mcOut.y = spImage.mouseY;
 
 // The visible cursor will correctly correspond to a depressed key.
 
 mcIn.visible = ke.ctrlKey;
 mcOut.visible = ke.shiftKey;
 
 // If either key (ctrl or shift) is depressed, we hide the mouse.
 if (ke.ctrlKey || ke.shiftKey) {
  Mouse.hide();
  moveMapCursor.visible=false;
  }
 else {
  moveMapCursor.visible=true;
 }
}

And here is the reset button code on it’s own for ease of reading/debug:


//Reset button activation so that view is restored
but_reset.addEventListener(MouseEvent.CLICK, resetMap);
function resetMap(e:MouseEvent):void {
  spImage.x = 0;
  spImage.y = 0;
  spImage.scaleX = spImage.scaleY = 1;
}

The code is made up of the board which contains the spImage container. The spImage has the image and controls in it. The idea of changing the scale of the spImage rather than the image itself is because it seems to stretch the image, messing up the resolution so I felt the easiest way would be to adjust the scale of spImage.

So, as stated earlier the main problem is that the reset breaks when you zoom in or out, but works perfectly otherwise, snapping to the top of spImage if the image itself has been dragged around. Maybe there is a way of setting a state and reverting back to this later?

If anyone can help me at all I would be very grateful.

Cheers,

KugarWeb