What is the Google Map zoom algorithm?

Let us state the problem in 1 dimension, with the input (left, right, clickx, ratio) So basically, you want to have the ratio to the click from the left and to the right to be the same:

Left'-clickx    right'-clickx
------------- = --------------
 left-clickx     right-clickx

and furthermore, the window is reduced, so:

right'-left'   
------------ = ratio
 right-left

Therefore, the solution is:

left'  = ratio*(left -clickx)+clickx
right' = ratio*(right-clickx)+clickx

And you can do the same for the other dimensions.


Lets say you have rectangle windowArea which holds drawing area coordinates(i.e web browser window area in pixels), for example if you are drawing map on the whole screen and the top left corner has coordinates (0, 0) then that rectangle will have values:

windowArea.top = 0;
windowArea.left = 0;
windowArea.right = maxWindowWidth;
windowArea.bottom = maxWindowHeight;

You also need to know visible map fragment, that will be longitude and latitude ranges, for example:

mapArea.top = 8.00; //lat
mapArea.left = 51.00; //lng
mapArea.right = 12.00; //lat
mapArea.bottom = 54.00; //lng

When zooming recalculate mapArea:

mapArea.left = mapClickPoint.x - (windowClickPoint.x- windowArea.left) * (newMapWidth / windowArea.width());
mapArea.top = mapClickPoint.y - (windowArea.bottom - windowClickPoint.y) * (newMapHeight / windowArea.height());
mapArea.right = mapArea.left + newWidth;
mapArea.bottom = mapArea.top + newHeight;

mapClickPoint holds map coordinates under mouse pointer(longitude, latitude). windowClickPoint holds window coordinates under mouse pointer(pixels).
newMapHeight and newMapWidth hold new ranges of visible map fragment after zoom:

newMapWidth = zoomFactor * mapArea.width;//lets say that zoomFactor = <1.0, maxZoomFactor>
newMapHeight = zoomFactor * mapArea.height;

When you have new mapArea values you need to stretch it to cover whole windowArea, that means mapArea.top/left should be drawn at windowArea.top/left and mapArea.right/bottom should be drawn at windowArea.right/bottom.

I am not sure if google maps use the same algorithms, it gives similar results and it is pretty versatile but you need to know window coordinates and some kind of coordinates for visible part of object that will be zoomed.

image