Building an OpenStreetMap Renderer from Scratch

EmailTwitterLinkedInFacebookWhatsAppShare

Understanding Web Mercator, tiles, pixels, and map math by implementing your own OSM renderer in pure JavaScript.


Introduction

Most developers use libraries like Leaflet, OpenLayers, or Mapbox GL to render maps. These libraries hide a huge amount of mathematics and geodesy behind a simple API.

But what actually happens when you:

  • Convert latitude/longitude to pixels?
  • Zoom in and out?
  • Drag the map?
  • See Greenland looking bigger than Africa?

In this article, we will build a minimal OpenStreetMap (OSM) renderer from scratch using HTML Canvas and JavaScript, and along the way understand:

  • Web Mercator Projection (EPSG:3857)
  • Tile pyramids
  • World coordinates vs pixels
  • Why the poles “explode”

This post is based on the complete working code shown below.


Full Source Code


Why OpenStreetMap Tiles Work

OpenStreetMap tiles follow a simple rule:

  • The world is projected using Web Mercator (EPSG:3857)
  • The world is split into 256×256 pixel tiles
  • At zoom level z, the world has 2^z × 2^z tiles
ZoomTiles AcrossWorld Size (px)
01256 × 256
12512 × 512
241024 × 1024
z2^z256 × 2^z

Web Mercator Projection (EPSG:3857)

Latitude / Longitude Reality

  • Longitude is linear (−180° → +180°)
  • Latitude is not linear on a flat surface

To draw the Earth on a rectangle, OSM uses the Mercator projection, originally designed for navigation.


Mercator Math (The Core Formula)

Forward Projection

We convert latitude and longitude into world coordinates.

x = (lon + 180) / 360

y = 0.5 - ln((1 + sin(lat)) / (1 - sin(lat))) / (4π)

Key idea:

  • Longitude maps linearly to X
  • Latitude uses a logarithmic function

This is why:

tan(90°) → ∞

And therefore:

The poles can never be drawn


Why Latitude Is Limited to ±85.0511°

If latitude reached ±90°:

ln(tan(π/4 + φ/2)) → ∞

So Web Mercator clamps latitude to:

±85.0511287798°

This makes the projected world finite and tileable.


World Coordinates vs Pixels

At zoom 0:

World = 256 × 256 pixels

At zoom z:

World size = 256 × 2^z pixels

Latitude/Longitude → World Pixels → Tile Pixels


Tiles: The Map Pyramid

Each tile:

  • Is 256×256 pixels
  • Has an address: {z}/{x}/{y}

Example:

https://tile.openstreetmap.org/4/8/6.png

Where:

  • z = zoom
  • x = column
  • y = row

Rendering Tiles on Canvas

Steps:

  1. Convert map center lat/lon → world pixels
  2. Compute visible world bounds
  3. Convert world bounds → tile range
  4. Load tiles
  5. Draw tiles at correct canvas position

This is exactly what mapping libraries do internally.


Panning (Dragging the Map)

Dragging does not immediately change latitude/longitude.

Instead:

  • We shift the view using pixel offsets
  • On mouse release, offsets are converted back to lat/lon

This makes panning smooth and precise.


Zooming

Zooming works by:

  • Increasing or decreasing z
  • Resetting offsets
  • Recomputing tile coverage

Every zoom level doubles map resolution.


Mouse Coordinate Conversion

To show mouse lat/lon:

  1. Convert canvas pixel → world pixel
  2. Convert world pixel → lat/lon (inverse Mercator)

This is how GIS tools show coordinates under the cursor.


Why Greenland Looks Bigger Than Africa

Mercator preserves:

  • Angles (good for navigation)

But distorts:

  • Area (bad for size comparison)

At high latitudes:

  • Scale factor increases dramatically
  • Land appears stretched vertically

This is a mathematical consequence of:

scale = 1 / cos(latitude)

What You Just Built

With ~500 lines of JavaScript, you implemented:

  • A Web Mercator projection engine
  • A tile-based renderer
  • Zoom and pan interaction
  • Coordinate conversion

You now understand what powers Leaflet, OpenLayers, Mapbox, Google Maps, and almost every web map.


When NOT to Use Web Mercator

Avoid EPSG:3857 when:

  • Accurate area matters
  • Polar regions are important
  • Scientific or climate analysis is required

Use equal-area or local projections instead.


Conclusion

Building a map renderer from scratch is the best way to truly understand GIS fundamentals.

Once you understand:

  • Projections
  • Tiles
  • Pixels
  • Zoom math

You stop treating maps as magic — and start treating them as geometry and math.

Happy mapping 🚀

I hope this tutorial will create a good foundation for you. If you want tutorials on another topic or you have any queries, please send an mail at contact@spatial-dev.guru.

Leave a ReplyCancel reply

Discover more from Spatial Dev Guru

Subscribe now to keep reading and get access to the full archive.

Continue reading

Discover more from Spatial Dev Guru

Subscribe now to keep reading and get access to the full archive.

Continue reading