<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Google Maps Platform</title>
    <description>The latest articles on Forem by Google Maps Platform (@googlemapsplatform).</description>
    <link>https://forem.com/googlemapsplatform</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F5165%2F11c60440-c19c-4cf5-81fb-44e4f3b29046.png</url>
      <title>Forem: Google Maps Platform</title>
      <link>https://forem.com/googlemapsplatform</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/googlemapsplatform"/>
    <language>en</language>
    <item>
      <title>So you have a lot of markers...</title>
      <dc:creator>Justin Poehnelt</dc:creator>
      <pubDate>Thu, 10 Feb 2022 01:27:19 +0000</pubDate>
      <link>https://forem.com/googlemapsplatform/so-you-have-a-lot-of-markers-to-display-on-your-map-3gb9</link>
      <guid>https://forem.com/googlemapsplatform/so-you-have-a-lot-of-markers-to-display-on-your-map-3gb9</guid>
      <description>&lt;p&gt;I often run into questions about how do I render XX,XXX markers on a map in a web application, specifically a &lt;code&gt;google.maps.Map()&lt;/code&gt; instance. The answer usually depends on the particular application requirements, but there are only a few good options.&lt;/p&gt;

&lt;h1&gt;
  
  
  Options
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Cluster the markers&lt;/li&gt;
&lt;li&gt;Use WebGL&lt;/li&gt;
&lt;li&gt;Write a custom OverlayView&lt;/li&gt;
&lt;li&gt;Render the markers server side&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Clustering &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Typically, I suggest starting with #1, clustering the markers. Two libraries to be aware of are &lt;a href="https://www.npmjs.com/package/@googlemaps/markerclusterer"&gt;@googlemaps/markerclusterer&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/supercluster"&gt;supercluster&lt;/a&gt;, a high performance kd-tree cluster implementation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w8tLgOwx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10qvvpqz37du9gsn3pow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w8tLgOwx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10qvvpqz37du9gsn3pow.png" alt="Marker clustering using @googlemaps/markerclusterer" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: @googlemaps/markerclusterer using supercluster internally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For React users, check out &lt;a href="https://www.npmjs.com/package/use-supercluster"&gt;use-supercluster&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>maps</category>
      <category>googlemaps</category>
      <category>markers</category>
      <category>performance</category>
    </item>
    <item>
      <title>Resources for Google Maps Platform</title>
      <dc:creator>Justin Poehnelt</dc:creator>
      <pubDate>Thu, 06 Jan 2022 17:09:50 +0000</pubDate>
      <link>https://forem.com/googlemapsplatform/resources-for-google-maps-platform-1573</link>
      <guid>https://forem.com/googlemapsplatform/resources-for-google-maps-platform-1573</guid>
      <description>&lt;p&gt;Everything starts at our &lt;a href="https://developers.google.com/maps"&gt;documentation&lt;/a&gt; including links to our other community resources such as &lt;a href="https://developers.google.com/maps/developer-community#github"&gt;GitHub&lt;/a&gt;, &lt;a href="https://discord.gg/f4hvx8Rp2q"&gt;Discord&lt;/a&gt;, and &lt;a href="https://developers.google.com/maps/developer-community#youtube"&gt;YouTube&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check our &lt;a href="https://developers.google.com/maps/support"&gt;support page&lt;/a&gt; for bugs, technical issues, feature requests, and more!&lt;/p&gt;

</description>
      <category>googlemaps</category>
      <category>support</category>
    </item>
    <item>
      <title>Google Maps React Wrapper</title>
      <dc:creator>Justin Poehnelt</dc:creator>
      <pubDate>Fri, 17 Sep 2021 23:17:44 +0000</pubDate>
      <link>https://forem.com/googlemapsplatform/google-maps-react-wrapper-17kd</link>
      <guid>https://forem.com/googlemapsplatform/google-maps-react-wrapper-17kd</guid>
      <description>&lt;p&gt;The package &lt;a href="https://www.npmjs.com/package/@googlemaps/react-wrapper"&gt;@googlemaps/react-wrapper&lt;/a&gt; is a wrapper component that helps load the Google Maps JavaScript API. Below is a short snippet demonstrating usage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Wrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@googlemaps/react-wrapper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LOADING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Spinner&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FAILURE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyApp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Wrapper&lt;/span&gt; &lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyMapComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Wrapper&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recently I livecoded its usage and created &lt;code&gt;google.maps.Map&lt;/code&gt; and &lt;code&gt;google.maps.Marker&lt;/code&gt; components.&lt;/p&gt;

&lt;p&gt;If you have any questions about its usage, please feel free to open an issue on &lt;a href="https://github.com/googlemaps/react-wrapper/issues"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>googlemaps</category>
      <category>react</category>
    </item>
    <item>
      <title>WMS Layer on Google Maps</title>
      <dc:creator>Justin Poehnelt</dc:creator>
      <pubDate>Sat, 19 Oct 2019 07:02:38 +0000</pubDate>
      <link>https://forem.com/googlemapsplatform/wms-layer-on-google-maps-1p1j</link>
      <guid>https://forem.com/googlemapsplatform/wms-layer-on-google-maps-1p1j</guid>
      <description>&lt;p&gt;The following code is now a package published to NPM at &lt;a href="https://www.npmjs.com/package/@googlemaps/ogc"&gt;&lt;strong&gt;@googlemaps/ogc&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://en.wikipedia.org/wiki/Web_Map_Service"&gt;Web Map Service(WMS)&lt;/a&gt; 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!&lt;/p&gt;

&lt;p&gt;Before jumping into JavaScript, we need to explore some XML and learn more about the WMS standard and tiled map numbering.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Web Map Service Standard
&lt;/h2&gt;

&lt;p&gt;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 &lt;a href="https://en.wikipedia.org/wiki/Web_Map_Service#Requests"&gt;GetCapabilities&lt;/a&gt; request to the WMS. Below is a extract of the response for the &lt;a href="https://www.mrlc.gov/data/nlcd-2016-land-cover-conus"&gt;National Land Cover Database&lt;/a&gt; server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Layer queryable="1" opaque="0"&amp;gt;
    &amp;lt;Name&amp;gt;mrlc_display:NLCD_2016_Land_Cover_L48&amp;lt;/Name&amp;gt;
    &amp;lt;Title&amp;gt;NLCD_2016_Land_Cover_L48&amp;lt;/Title&amp;gt;
    &amp;lt;Abstract/&amp;gt;
    &amp;lt;KeywordList&amp;gt;
        &amp;lt;Keyword&amp;gt;NLCD_2016_Land_Cover_L48_20210604_3857&amp;lt;/Keyword&amp;gt;
        &amp;lt;Keyword&amp;gt;WCS&amp;lt;/Keyword&amp;gt;
        &amp;lt;Keyword&amp;gt;ERDASImg&amp;lt;/Keyword&amp;gt;
    &amp;lt;/KeywordList&amp;gt;
    &amp;lt;CRS&amp;gt;EPSG:3857&amp;lt;/CRS&amp;gt;
    &amp;lt;CRS&amp;gt;CRS:84&amp;lt;/CRS&amp;gt;
    &amp;lt;EX_GeographicBoundingBox&amp;gt;
        &amp;lt;westBoundLongitude&amp;gt;-130.23282801589895&amp;lt;/westBoundLongitude&amp;gt;
        &amp;lt;eastBoundLongitude&amp;gt;-63.6719773760062&amp;lt;/eastBoundLongitude&amp;gt;
        &amp;lt;southBoundLatitude&amp;gt;21.742250095963353&amp;lt;/southBoundLatitude&amp;gt;
        &amp;lt;northBoundLatitude&amp;gt;52.87726396463256&amp;lt;/northBoundLatitude&amp;gt;
    &amp;lt;/EX_GeographicBoundingBox&amp;gt;
    &amp;lt;BoundingBox CRS="CRS:84" minx="-130.23282801589895" miny="21.742250095963353" maxx="-63.6719773760062" maxy="52.87726396463256"/&amp;gt;
    &amp;lt;BoundingBox CRS="EPSG:3857" minx="-1.4497452099297844E7" miny="2480607.2664330592" maxx="-7087932.099297844" maxy="6960327.266433059"/&amp;gt;
    &amp;lt;Style&amp;gt;
        &amp;lt;Name&amp;gt;mrlc:mrlc_NLCD_Land_Cover&amp;lt;/Name&amp;gt;
        &amp;lt;Title&amp;gt;A boring default style&amp;lt;/Title&amp;gt;
        &amp;lt;Abstract&amp;gt;A sample style for rasters&amp;lt;/Abstract&amp;gt;
        &amp;lt;LegendURL width="261" height="509"&amp;gt;
            &amp;lt;Format&amp;gt;image/png&amp;lt;/Format&amp;gt;
            &amp;lt;OnlineResource
                xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="https://www.mrlc.gov/geoserver/ows?service=WMS&amp;amp;request=GetLegendGraphic&amp;amp;format=image%2Fpng&amp;amp;width=20&amp;amp;height=20&amp;amp;layer=mrlc_display%3ANLCD_2016_Land_Cover_L48"/&amp;gt;
            &amp;lt;/LegendURL&amp;gt;
        &amp;lt;/Style&amp;gt;
    &amp;lt;/Layer&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These options become query parameters in our GetMap request to the WMS returning the following.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ps7AzKU4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://justin.poehnelt.com/images/dEJe5W3LZJ-200.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ps7AzKU4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://justin.poehnelt.com/images/dEJe5W3LZJ-200.jpeg" alt="NLCD 2016 Land Cover L48" width="200" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NLCD 2016 Land Cover L48&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.mrlc.gov/geoserver/NLCD_Land_Cover/wms?
&amp;amp;REQUEST=GetMap
&amp;amp;SERVICE=WMS
&amp;amp;VERSION=1.1.1
&amp;amp;LAYERS=mrlc_display:NLCD_2016_Land_Cover_L48
&amp;amp;FORMAT=image/png
&amp;amp;SRS=EPSG:3857  // Web Mercator
&amp;amp;BBOX=-10175297.20791413,5165920.120941021,-10018754.17394622,5322463.154908929 // Coordinates in Web Mecator
&amp;amp;WIDTH=1024
&amp;amp;HEIGHT=1024
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is important to note that the coordinates for the &lt;code&gt;BBOX&lt;/code&gt; parameter must be in the coordinate reference system specified by the spatial reference system(SRS). In the above request we are using &lt;a href="https://epsg.io/3857"&gt;&lt;code&gt;EPSG:3857&lt;/code&gt;&lt;/a&gt;, also known as &lt;strong&gt;web mercator&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Web Mercator&lt;/strong&gt; , &lt;strong&gt;Google Web Mercator&lt;/strong&gt; , &lt;strong&gt;Spherical Mercator&lt;/strong&gt; , &lt;strong&gt;WGS 84 Web Mercator&lt;/strong&gt; &lt;a href="https://en.wikipedia.org/wiki/Web_Mercator_projection#cite_note-1"&gt;[1]&lt;/a&gt; or &lt;strong&gt;WGS 84/Pseudo-Mercator&lt;/strong&gt; is a constiant of the &lt;a href="https://en.wikipedia.org/wiki/Mercator_projection"&gt;Mercator projection&lt;/a&gt; and is the &lt;a href="https://en.wikipedia.org/wiki/De_facto_standard"&gt;de facto standard&lt;/a&gt; for &lt;a href="https://en.wikipedia.org/wiki/World_Wide_Web"&gt;Web&lt;/a&gt; mapping applications. It rose to prominence when &lt;a href="https://en.wikipedia.org/wiki/Google_Maps"&gt;Google Maps&lt;/a&gt; adopted it in 2005. — &lt;a href="https://en.wikipedia.org/wiki/Web_Mercator_projection"&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Google Maps &lt;code&gt;ImageMapType&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;google.maps.ImageMapType&lt;/code&gt; and &lt;code&gt;google.maps.ImageMapTypeOptions&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PQiWlYIL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://justin.poehnelt.com/images/Fh41t-eX65-200.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PQiWlYIL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://justin.poehnelt.com/images/Fh41t-eX65-200.jpeg" alt="Interface for google.maps.ImageMapType" width="200" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Interface for google.maps.ImageMapType&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;getTileUrl&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are two primary steps to creating the getTileUrl function:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Convert point into web mercator coordinates.&lt;/li&gt;
&lt;li&gt;Assemble the WMS URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tile(Point and Zoom) to Web Mercator Coordinates
&lt;/h2&gt;

&lt;p&gt;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 &lt;code&gt;getTileUrl&lt;/code&gt; function we will write.&lt;/p&gt;

&lt;p&gt;Most tiled web maps follow certain Google Maps conventions:&lt;/p&gt;

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

&lt;p&gt;With the above conventions, we know that at zoom level 1, the world is divided into 4 tiles with the coordinates depicted below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vcUKap_8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://justin.poehnelt.com/images/W7FEEg820f-200.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vcUKap_8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://justin.poehnelt.com/images/W7FEEg820f-200.jpeg" alt="XYZ Tile Map Pattern" width="200" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;XYZ Tile Map Pattern&lt;/p&gt;

&lt;p&gt;We also know that the web mercator extent is a square and its bounds are &lt;code&gt;-PI * 6378137, PI * 6378137&lt;/code&gt;. Given the above, we can convert from &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, and &lt;code&gt;z&lt;/code&gt; to coordinates using the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const EXTENT = [-Math.PI * 6378137, Math.PI * 6378137];

function xyzToBounds(x, y, z) {
    const tileSize = EXTENT[1] * 2 / Math.pow(2, z);
    const minx = EXTENT[0] + x * tileSize;
    const maxx = EXTENT[0] + (x + 1) * tileSize;
    // remember y origin starts at top
    const miny = EXTENT[1] - (y + 1) * tileSize;
    const maxy = EXTENT[1] - y * tileSize;
    return [minx, miny, maxx, maxy];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling &lt;code&gt;xyzToBounds(0, 0, 1)&lt;/code&gt; returns &lt;code&gt;[-20037508.342789244, 0, 0, 20037508.342789244]&lt;/code&gt; which is what we would expect for the upper left tile in the diagram above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assemble the WMS URL
&lt;/h2&gt;

&lt;p&gt;The next step is assembling the string for the WMS getMap URL with the function defined above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getTileUrl = (coordinates, zoom) =&amp;gt; {
  return (
    "https://www.mrlc.gov/geoserver/NLCD_Land_Cover/wms?" +
    "&amp;amp;REQUEST=GetMap&amp;amp;SERVICE=WMS&amp;amp;VERSION=1.1.1" +
    "&amp;amp;LAYERS=mrlc_display%3ANLCD_2016_Land_Cover_L48" +
    "&amp;amp;FORMAT=image%2Fpng" +
    "&amp;amp;SRS=EPSG:3857&amp;amp;WIDTH=256&amp;amp;HEIGHT=256" +
    "&amp;amp;BBOX=" +
    xyzToBounds(coordinates.x, coordinates.y, zoom).join(",")
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Putting it All Together
&lt;/h2&gt;

&lt;p&gt;Now that we have our &lt;code&gt;getTileUrl&lt;/code&gt; function, we can construct our &lt;code&gt;ImageMapType&lt;/code&gt;. Don’t forget that &lt;code&gt;maxZoom&lt;/code&gt; is required! See reference table above or &lt;a href="https://developers.google.com/maps/documentation/javascript/reference"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const landCover = new google.maps.ImageMapType({
  getTileUrl: getTileUrl,
  name: "Land Cover",
  alt: "National Land Cover Database 2016",
  minZoom: 0,
  maxZoom: 19,
  opacity: 1.0map
});

landCover.setMap(map);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add it to our map! See this &lt;a href="https://jsfiddle.net/jwpoehnelt/1ph0wen3"&gt;JSFiddle link&lt;/a&gt; for an interactive example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q7UcFd67--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://justin.poehnelt.com/images/nxPxElKvIt-200.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q7UcFd67--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://justin.poehnelt.com/images/nxPxElKvIt-200.jpeg" alt="NLCD 2016 Land Cover L48" width="200" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NLCD 2016 Land Cover L48&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

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

</description>
      <category>wms</category>
      <category>googlemaps</category>
      <category>ogc</category>
    </item>
  </channel>
</rss>
