Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Maps Javascript API with an OpenWeatherMap Tile Layer Overlay

How can I overlay an XYZ tile set (something like this) on Google Maps API 3? I want to overlay weather data (cloud cover...etc). Feel free to use my OpenWeatherMaps URL to test it out:

http://maps.owm.io:8091/56ce0fcd4376d3010038aaa8/{z}/{x}/{y}?hash=5

I have spent multiple days trying to figure out this seemingly simple feature. If someone can provide a working example I would be in your debt. Feel free to check out my GitHub Gist implementation using OL3 and OSM of this weather data overlay. I'd also love to know if this is not easily achievable/requires hacks.

Thank you!

Update: Thanks to @wf9a5m75's answer, I was able to put together this jsFiddle with the solution to my problem: https://jsfiddle.net/601oqwq2/4/

like image 907
Karl Floersch Avatar asked Mar 04 '16 19:03

Karl Floersch


2 Answers

ImageMapType is for your purpose. Read here: https://developers.google.com/maps/documentation/javascript/maptypes#ImageMapTypes

    var myMapType = new google.maps.ImageMapType({
      getTileUrl: function(coord, zoom) {
        return "http://maps.owm.io:8091/56ce0fcd4376d3010038aaa8/" + 
               zoom + "/" + coord.x + "/" + coord.y + "?hash=5";
    },
    tileSize: new google.maps.Size(256, 256),
    maxZoom: 9,
    minZoom: 0,
    name: 'mymaptype'
  });

  map.mapTypes.set('mymaptype', myMapType);
  map.setMapTypeId('mymaptype');

[update] Overlay the imageMapType above the current mapType

    var map = new google.maps.Map(document.getElementById('map'), {
      center: {lat: -34.397, lng: 150.644},
      zoom: 8
    });

    var myMapType = new google.maps.ImageMapType({
      getTileUrl: function(coord, zoom) {
        return "http://maps.owm.io:8091/56ce0fcd4376d3010038aaa8/" + 
               zoom + "/" + coord.x + "/" + coord.y + "?hash=5";
      },
      tileSize: new google.maps.Size(256, 256),
      maxZoom: 9,
      minZoom: 0,
      name: 'mymaptype'
    });

    map.overlayMapTypes.insertAt(0, myMapType);

enter image description here

like image 155
wf9a5m75 Avatar answered Dec 12 '22 17:12

wf9a5m75


Improving on wf9a5m75's answer.

The overlay image tiles don't cover the underlying map when zoomed out. We can make use of a normalization function (as mentioned in the link here) to ensure they cover the whole area.

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
#map {
  height: 100%;
}
<body>
  <div id="map"></div>
  <script>
    var map;

    function initMap() {
      var map = new google.maps.Map(document.getElementById('map'), {
        center: {
          lat: 19.0356826,
          lng: 72.9112641
        },
        zoom: 6,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        disableDefaultUI: true
      });

      var myMapType = new google.maps.ImageMapType({
        getTileUrl: function(coord, zoom) {
          var normalizedCoord = getNormalizedCoord(coord, zoom);
          if (!normalizedCoord) {
            return null;
          }
          var bound = Math.pow(2, zoom);
          return "http://maps.owm.io:8091/56ce0fcd4376d3010038aaa8/" +
            zoom + "/" + normalizedCoord.x + "/" + (bound - normalizedCoord.y - 1) + "?hash=5";
        },
        tileSize: new google.maps.Size(256, 256),
        maxZoom: 8,
        minZoom: 0,
        name: 'mymaptype'
      });

      // Normalizes the coords that tiles repeat across the x axis (horizontally)
      // like the standard Google map tiles.
      function getNormalizedCoord(coord, zoom) {
        var y = coord.y;
        var x = coord.x;

        // tile range in one direction range is dependent on zoom level
        // 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
        var tileRange = 1 << zoom;

        // don't repeat across y-axis (vertically)
        if (y < 0 || y >= tileRange) {
          return null;
        }

        // repeat across x-axis
        if (x < 0 || x >= tileRange) {
          x = (x % tileRange + tileRange) % tileRange;
        }

        return {
          x: x,
          y: y
        };
      }

      map.overlayMapTypes.insertAt(0, myMapType);
    }
  </script>
  <script src="https://maps.googleapis.com/maps/api/js?callback=initMap" async defer></script>
</body>

Results

like image 37
Ashesh Avatar answered Dec 12 '22 19:12

Ashesh