An illustration with the text: Pan pan Pan pan

Writing a map library from scratch - Part 3: Panning


If you haven’t read Part 1 and Part 2 yet, I recommend you do so before continuing.


In the previous article, we implemented zooming. Now, we’ll look at panning. How does it work?

Panning

In a nutshell, panning is when you click and drag the map to move it around. It’s pretty straight forward: you just need to calculate the difference between the cursor position when the click/tap starts and when you release it, then move the map center by that amount.

Panning Demo

Calculating the difference

Let us have the center at (x0, y0) and the cursor position at (x1, y1), where also the panning starts. The panning ends at (x2, y2). The new center will then be at:

x0 = x0 + (x2 - x1);
y0 = y0 + (y2 - y1);

Example

Let us take the same map from the previous articles:

  • The center is:(13.4, 52.52).
  • The zoom level is 14.
  • One tile is 256 pixels wide and high.
  • The map is inside a container of 400 pixels width and 300 pixels height.
  • The center of the container is at (200, 150).

Using the Web Mercator Projection, these geo-coordinates (on a globe) can be converted to (2253273.3155555557, 1375543.6427981234) in cartesian coordinates (on a flat surface). Let’s say the mouse cursor is at (100, 150) inside the container, and we move the cursor while clicking/tapping to (300, 350). Using our formula, the new cartesian center will be:

x0 = 200 + (300 - 100);
x0 = 400;

y0 = 150 + (350 - 150);
y0 = 350

So the cartesian coordinates of the new center are:

x0 = 2253273.3155555557 + (300 - 100);
x0 = 2253473.3155555557;

y0 = 1375543.6427981234 + (350 - 150);
y0 = 1375743.6427981234;

And just like before, we need to use the web mercator projection to convert these cartesian coordinates to geographic coordinates.

axisSize = 4194304 // 256*2^14

lng = 360 * (x0 / axisSize - 0.5);
lng = 13.417166137695329;
lat = 360 * (Math.atan(Math.exp(Math.PI * (1 - (2 * y0) / axisSize))) / Math.PI - 0.25);
lat = 52.50955343022076 ;

If we plug those values back into the algorithm from Part 1, we can pan (click/tap and drag the map):

Tile displaying a part of a map
Tile displaying a part of a map
Tile displaying a part of a map
Tile displaying a part of a map

Panning Map of Berlin (Source)