UPDATE: The following code is now a package published to NPM at @googlemaps/ogc.

A Web Map Service(WMS) is a 20 year old standard for serving georeferenced images over HTTP. Google Maps allows developers to add custom map types. Let’s see how we combine the two!

Before jumping into JavaScript, we need to explore some XML and learn more about the WMS standard and tiled map numbering.

tl;dr: Checkout the jsfiddle at https://jsfiddle.net/jwpoehnelt/1ph0wen3.

Web Map Service

The WMS standard exposes many options such as coordinate reference systems(CRS), bounding box, and style selection. These parameters are specified in an XML document that can be queried by sending a GetCapabilities request to the WMS. Below is a extract of the response for the National Land Cover Database server.

These options become query parameters in our GetMap request to the WMS becoming the image below.

It is important to note that the coordinates for the BBOX parameter must be in the coordinate reference system specified by the spatial reference system(SRS). In the above request we are using EPSG:3857, also known as web mercator.

Web Mercator, Google Web Mercator, Spherical Mercator, WGS 84 Web Mercator[1] or WGS 84/Pseudo-Mercator is a variant of the Mercator projection and is the de facto standard for Web mapping applications. It rose to prominence when Google Maps adopted it in 2005. — Wikipedia

Google Maps ImageMapType

Now that we have a basic understanding how the HTTP request to retrieve imagery from a WMS, we can begin exploring the interface Google Maps exposes for its map types, specifically the google.maps.ImageMapType and google.maps.ImageMapTypeOptions.

You getTileUrl is the option required to enable a WMS layer in Google Maps and how we create that tile URL must follow the WMS standard discussed above.

There are two primary steps to creating the getTileUrl function:

  1. Convert point into web mercator coordinates.
  2. Assemble the WMS URL.

Tile(Point and Zoom) to Web Mercator Coordinates

Before diving into the simple math of calculating the web mercator coordinates, we need to understand a little more about tiled web maps and the parameters of the getTileUrl function we will write.

Most tiled web maps follow certain Google Maps conventions:

  • Tiles are 256x256 pixels
  • At the outer most zoom level, 0, the entire world can be rendered in a single map tile.
  • Each zoom level doubles in both dimensions, so a single tile is replaced by 4 tiles when zooming in.

With the above conventions, we know that at zoom level 1, the world is divided into 4 tiles with the coordinates depicted below.

We also know that the web mercator extent is a square and its bounds are [-PI * 6378137, PI * 6378137]. Given the above, we can convert from x, y, and z to coordinates using the following:

Calling xyzToBounds(0, 0, 1) returns [-20037508.342789244, 0, 0, 20037508.342789244] which is what we would expect for the upper left tile in the diagram above.

Assemble the WMS URL

The next step is assembling the string for the WMS getMap URL with the function defined above.

Putting it All Together

Now that we have our getTileUrl function, we can construct out ImageMapType. Don’t forget that maxZoom is required! See reference table above or here.

And add it to our map! See this jsfiddle link for an interactive example.

Notes

  • XZY, TMS, WTMS will likely be optimized for many simultaneous requests and should be used over WMS when possible.
  • TMS is very similar to XYZ except for the order of y.
  • Not all WMS will support EPSG:3857 but it is possible to do the calculation to EPSG:4326 coordinates(latitude and longitude) which may be more commonly supported.

Developer Programs Engineer @ Google