Simulate Zoom In/Out Using Scroll View

Hi,

I have a GUI menu in a game I’m working on that allows the player to view a world map. The map is a texture I created and imported into my project. I’m trying to use the scroll view within the map menu to not only allow the player to scroll up/down and left right on the map, but also zoom in/out. I have it working, but not exactly the way it should. The map size is larger than the view rect so I can scroll left/right and up/down to view more of the map within the scroll view. I also have zoom in/out buttons that change the size of the texture as well as the scroll view which simulates the player zooming in/out on the map. However, the position of the scroll bars do not stay with the area of the map that is currently shown within the view rect when I zoom in/out. For example, the middle of the scroll view shows a town on the map…when I click the zoom in button the town on the map should still be the focus point, but instead it shifts down and to the side. The code is provided below. Within the logic for the + and - buttons, how would I manipulate mapScrollPos so that the horizontal and vertical scroll bar positions change to keep the town focused in the center. Please let me know if my explanation was too confusing.

public class MapMenu : MonoBehaviour {

public bool toggleMap;

Texture worldMap;

float mapZoomX = .8f;
float mapZoomY = .8f;

private Vector2 mapScrollPos;
private Rect mapScrollViewPos = new Rect((Screen.width * .325f),((Screen.height/2)-280),(Screen.width * .48f),(Screen.height * .56f));

void Start () {

	worldMap = (Texture2D)Resources.Load("Textures/Test World Map");
}

void OnGUI() {

if(GUI.Button (new Rect(((Screen.width)*(.165f)), (Screen.height / 2) - 220, 120, 30), "Map")) {
      toggleMap = true;
}

	Rect mapScrollView = new Rect((Screen.width * .325f),((Screen.height/2)-280),(Screen.width * mapZoomX)(Screen.height * mapZoomY));

if(toggleMap) {
				GUI.Box (new Rect(((Screen.width)*(.325f)), (Screen.height / 2) - 280, (Screen.width * .48f), (Screen.height * .56f)), "");
				GUI.Label (new Rect(((Screen.width)*(.55f)), (Screen.height / 2) - 310, 200, 30), "Map");

				if(GUI.Button(new Rect((Screen.width) * (.3f), (Screen.height /2) - 270 , (Screen.width) * (.025f), 30), "+")) {
					if(mapZoomX < 1.5f  mapZoomY < 1.5f) {
						mapZoomX += .1f;
						mapZoomY += .1f;
					}
				}
				
				if(GUI.Button(new Rect((Screen.width) * (.3f), (Screen.height /2) - 240 , (Screen.width) * (.025f), 30), "-")) {
					if(mapZoomX > .8f  mapZoomY > .8f) {
						mapZoomX -= .1f;
						mapZoomY -= .1f;
					}
				}

				// Build scroll area and map
				mapScrollPos = GUI.BeginScrollView (mapScrollViewPos, mapScrollPos, mapScrollView);
				GUI.DrawTexture(new Rect((Screen.width * .325f), ((Screen.height/2)-280), (Screen.width * (mapZoomX)), (Screen.height * (mapZoomY))), worldMap);
				GUI.EndScrollView ();
				// End scroll area and map

				// Logic for map goes here
			}
      }
}

Line 24 is missing a comma.
Shouldn’t 20-22 be a GUI.toggle?

Id suggest merging mapZoomX and mapZoomY into a single mapZoom property, i can’t really see you wanting to change the scale of each axis independantly, because then you get ugly stretching.

Put the following blocks into the zoom buttons:

//Zoom in button:
mapZoom += .1f;
float centerX = mapScrollPos.x + mapScrollViewPos.width / 2;
float centerY = mapScrollPos.y + mapScrollViewPos.height / 2;
float zoomFactor = mapZoom / ( mapZoom - .1f );
centerX *= zoomFactor;
centerY *= zoomFactor;

mapScrollPos = new Vector2( centerX - mapScrollViewPos.width / 2, centerY - mapScrollViewPos.height / 2 );


//Zoom out button:
mapZoom -= .1f;
float centerX = mapScrollPos.x + mapScrollViewPos.width / 2;
float centerY = mapScrollPos.y + mapScrollViewPos.height / 2;
float zoomFactor = mapZoom / ( mapZoom + .1f );
centerX *= zoomFactor;
centerY *= zoomFactor;

mapScrollPos = new Vector2( centerX - mapScrollViewPos.width / 2, centerY - mapScrollViewPos.height / 2 );