It's the 15th anniversary of Google Maps Platform - Check out the latest news and announcements

Custom Map Projections

This example creates a map using the Gall-Peters projection, rather than the default Mercator projection.

Read the documentation.

TypeScript

// This example defines an image map type using the Gall-Peters
// projection.
// https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection

function initMap(): void {
  // Create a map. Use the Gall-Peters map type.
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 0,
      center: { lat: 0, lng: 0 },
      mapTypeControl: false
    }
  );

  initGallPeters();
  map.mapTypes.set("gallPeters", gallPetersMapType);
  map.setMapTypeId("gallPeters");

  // Show the lat and lng under the mouse cursor.
  const coordsDiv = document.getElementById("coords") as HTMLElement;
  map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv);
  map.addListener("mousemove", (event: google.maps.MouseEvent) => {
    coordsDiv.textContent =
      "lat: " +
      Math.round(event.latLng.lat()) +
      ", " +
      "lng: " +
      Math.round(event.latLng.lng());
  });

  // Add some markers to the map.
  map.data.setStyle(feature => {
    return {
      title: feature.getProperty("name"),
      optimized: false
    };
  });
  map.data.addGeoJson(cities);
}

let gallPetersMapType;

function initGallPeters() {
  const GALL_PETERS_RANGE_X = 800;
  const GALL_PETERS_RANGE_Y = 512;

  // Fetch Gall-Peters tiles stored locally on our server.
  gallPetersMapType = new google.maps.ImageMapType({
    getTileUrl: function(coord, zoom) {
      const scale = 1 << zoom;

      // Wrap tiles horizontally.
      const x = ((coord.x % scale) + scale) % scale;

      // Don't wrap tiles vertically.
      const y = coord.y;

      if (y < 0 || y >= scale) return "";

      return (
        "https://developers.google.com/maps/documentation/" +
        "javascript/examples/full/images/gall-peters_" +
        zoom +
        "_" +
        x +
        "_" +
        y +
        ".png"
      );
    },
    tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y),
    minZoom: 0,
    maxZoom: 1,
    name: "Gall-Peters"
  });

  // Describe the Gall-Peters projection used by these tiles.
  gallPetersMapType.projection = {
    fromLatLngToPoint: function(latLng) {
      const latRadians = (latLng.lat() * Math.PI) / 180;
      return new google.maps.Point(
        GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
        GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians))
      );
    },
    fromPointToLatLng: function(point, noWrap) {
      const x = point.x / GALL_PETERS_RANGE_X;
      const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y));

      return new google.maps.LatLng(
        (Math.asin(1 - 2 * y) * 180) / Math.PI,
        -180 + 360 * x,
        noWrap
      );
    }
  };
}

// GeoJSON, describing the locations and names of some cities.
const cities = {
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-87.65, 41.85] },
      properties: { name: "Chicago" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-149.9, 61.218] },
      properties: { name: "Anchorage" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-99.127, 19.427] },
      properties: { name: "Mexico City" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-0.126, 51.5] },
      properties: { name: "London" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [28.045, -26.201] },
      properties: { name: "Johannesburg" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [15.322, -4.325] },
      properties: { name: "Kinshasa" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [151.207, -33.867] },
      properties: { name: "Sydney" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [0, 0] },
      properties: { name: "0°N 0°E" }
    }
  ]
};

JavaScript

// This example defines an image map type using the Gall-Peters
// projection.
// https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection
function initMap() {
  // Create a map. Use the Gall-Peters map type.
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 0,
    center: { lat: 0, lng: 0 },
    mapTypeControl: false
  });
  initGallPeters();
  map.mapTypes.set("gallPeters", gallPetersMapType);
  map.setMapTypeId("gallPeters");
  // Show the lat and lng under the mouse cursor.
  const coordsDiv = document.getElementById("coords");
  map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv);
  map.addListener("mousemove", event => {
    coordsDiv.textContent =
      "lat: " +
      Math.round(event.latLng.lat()) +
      ", " +
      "lng: " +
      Math.round(event.latLng.lng());
  });
  // Add some markers to the map.
  map.data.setStyle(feature => {
    return {
      title: feature.getProperty("name"),
      optimized: false
    };
  });
  map.data.addGeoJson(cities);
}
let gallPetersMapType;

function initGallPeters() {
  const GALL_PETERS_RANGE_X = 800;
  const GALL_PETERS_RANGE_Y = 512;
  // Fetch Gall-Peters tiles stored locally on our server.
  gallPetersMapType = new google.maps.ImageMapType({
    getTileUrl: function(coord, zoom) {
      const scale = 1 << zoom;
      // Wrap tiles horizontally.
      const x = ((coord.x % scale) + scale) % scale;
      // Don't wrap tiles vertically.
      const y = coord.y;

      if (y < 0 || y >= scale) return "";
      return (
        "https://developers.google.com/maps/documentation/" +
        "javascript/examples/full/images/gall-peters_" +
        zoom +
        "_" +
        x +
        "_" +
        y +
        ".png"
      );
    },
    tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y),
    minZoom: 0,
    maxZoom: 1,
    name: "Gall-Peters"
  });
  // Describe the Gall-Peters projection used by these tiles.
  gallPetersMapType.projection = {
    fromLatLngToPoint: function(latLng) {
      const latRadians = (latLng.lat() * Math.PI) / 180;
      return new google.maps.Point(
        GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
        GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians))
      );
    },
    fromPointToLatLng: function(point, noWrap) {
      const x = point.x / GALL_PETERS_RANGE_X;
      const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y));
      return new google.maps.LatLng(
        (Math.asin(1 - 2 * y) * 180) / Math.PI,
        -180 + 360 * x,
        noWrap
      );
    }
  };
}
// GeoJSON, describing the locations and names of some cities.
const cities = {
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-87.65, 41.85] },
      properties: { name: "Chicago" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-149.9, 61.218] },
      properties: { name: "Anchorage" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-99.127, 19.427] },
      properties: { name: "Mexico City" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [-0.126, 51.5] },
      properties: { name: "London" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [28.045, -26.201] },
      properties: { name: "Johannesburg" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [15.322, -4.325] },
      properties: { name: "Kinshasa" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [151.207, -33.867] },
      properties: { name: "Sydney" }
    },
    {
      type: "Feature",
      geometry: { type: "Point", coordinates: [0, 0] },
      properties: { name: "0°N 0°E" }
    }
  ]
};

CSS

/* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
#map {
  height: 100%;
}

/* Optional: Makes the sample page fill the window. */
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

#coords {
  background-color: black;
  color: white;
  padding: 5px;
}

HTML

<!DOCTYPE html>
<html>
  <head>
    <title>Custom Map Projections</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    <script
      src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap&libraries=&v=weekly"
      defer
    ></script>
    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script src="./app.js"></script>
  </head>
  <body>
    <div id="map"></div>
    <div id="coords"></div>
  </body>
</html>

All

<!DOCTYPE html>
<html>
  <head>
    <title>Custom Map Projections</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    <script
      src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap&libraries=&v=weekly"
      defer
    ></script>
    <style type="text/css">
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }

      /* Optional: Makes the sample page fill the window. */
      html,
      body {
        height: 100%;
        margin: 0;
        padding: 0;
      }

      #coords {
        background-color: black;
        color: white;
        padding: 5px;
      }
    </style>
    <script>
      "use strict";

      // This example defines an image map type using the Gall-Peters
      // projection.
      // https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection
      function initMap() {
        // Create a map. Use the Gall-Peters map type.
        const map = new google.maps.Map(document.getElementById("map"), {
          zoom: 0,
          center: {
            lat: 0,
            lng: 0
          },
          mapTypeControl: false
        });
        initGallPeters();
        map.mapTypes.set("gallPeters", gallPetersMapType);
        map.setMapTypeId("gallPeters"); // Show the lat and lng under the mouse cursor.

        const coordsDiv = document.getElementById("coords");
        map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv);
        map.addListener("mousemove", event => {
          coordsDiv.textContent =
            "lat: " +
            Math.round(event.latLng.lat()) +
            ", " +
            "lng: " +
            Math.round(event.latLng.lng());
        }); // Add some markers to the map.

        map.data.setStyle(feature => {
          return {
            title: feature.getProperty("name"),
            optimized: false
          };
        });
        map.data.addGeoJson(cities);
      }

      let gallPetersMapType;

      function initGallPeters() {
        const GALL_PETERS_RANGE_X = 800;
        const GALL_PETERS_RANGE_Y = 512; // Fetch Gall-Peters tiles stored locally on our server.

        gallPetersMapType = new google.maps.ImageMapType({
          getTileUrl: function(coord, zoom) {
            const scale = 1 << zoom; // Wrap tiles horizontally.

            const x = ((coord.x % scale) + scale) % scale; // Don't wrap tiles vertically.

            const y = coord.y;
            if (y < 0 || y >= scale) return "";
            return (
              "https://developers.google.com/maps/documentation/" +
              "javascript/examples/full/images/gall-peters_" +
              zoom +
              "_" +
              x +
              "_" +
              y +
              ".png"
            );
          },
          tileSize: new google.maps.Size(
            GALL_PETERS_RANGE_X,
            GALL_PETERS_RANGE_Y
          ),
          minZoom: 0,
          maxZoom: 1,
          name: "Gall-Peters"
        }); // Describe the Gall-Peters projection used by these tiles.

        gallPetersMapType.projection = {
          fromLatLngToPoint: function(latLng) {
            const latRadians = (latLng.lat() * Math.PI) / 180;
            return new google.maps.Point(
              GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360),
              GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians))
            );
          },
          fromPointToLatLng: function(point, noWrap) {
            const x = point.x / GALL_PETERS_RANGE_X;
            const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y));
            return new google.maps.LatLng(
              (Math.asin(1 - 2 * y) * 180) / Math.PI,
              -180 + 360 * x,
              noWrap
            );
          }
        };
      } // GeoJSON, describing the locations and names of some cities.

      const cities = {
        type: "FeatureCollection",
        features: [
          {
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [-87.65, 41.85]
            },
            properties: {
              name: "Chicago"
            }
          },
          {
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [-149.9, 61.218]
            },
            properties: {
              name: "Anchorage"
            }
          },
          {
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [-99.127, 19.427]
            },
            properties: {
              name: "Mexico City"
            }
          },
          {
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [-0.126, 51.5]
            },
            properties: {
              name: "London"
            }
          },
          {
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [28.045, -26.201]
            },
            properties: {
              name: "Johannesburg"
            }
          },
          {
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [15.322, -4.325]
            },
            properties: {
              name: "Kinshasa"
            }
          },
          {
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [151.207, -33.867]
            },
            properties: {
              name: "Sydney"
            }
          },
          {
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [0, 0]
            },
            properties: {
              name: "0°N 0°E"
            }
          }
        ]
      };
    </script>
  </head>
  <body>
    <div id="map"></div>
    <div id="coords"></div>
  </body>
</html>
"use strict"; // This example defines an image map type using the Gall-Peters // projection. // https://en.wikipedia.org/wiki/Gall%E2%80%93Peters_projection function initMap() { // Create a map. Use the Gall-Peters map type. const map = new google.maps.Map(document.getElementById("map"), { zoom: 0, center: { lat: 0, lng: 0 }, mapTypeControl: false }); initGallPeters(); map.mapTypes.set("gallPeters", gallPetersMapType); map.setMapTypeId("gallPeters"); // Show the lat and lng under the mouse cursor. const coordsDiv = document.getElementById("coords"); map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv); map.addListener("mousemove", event => { coordsDiv.textContent = "lat: " + Math.round(event.latLng.lat()) + ", " + "lng: " + Math.round(event.latLng.lng()); }); // Add some markers to the map. map.data.setStyle(feature => { return { title: feature.getProperty("name"), optimized: false }; }); map.data.addGeoJson(cities); } let gallPetersMapType; function initGallPeters() { const GALL_PETERS_RANGE_X = 800; const GALL_PETERS_RANGE_Y = 512; // Fetch Gall-Peters tiles stored locally on our server. gallPetersMapType = new google.maps.ImageMapType({ getTileUrl: function(coord, zoom) { const scale = 1 << zoom; // Wrap tiles horizontally. const x = ((coord.x % scale) + scale) % scale; // Don't wrap tiles vertically. const y = coord.y; if (y < 0 || y >= scale) return ""; return ( "https://developers.google.com/maps/documentation/" + "javascript/examples/full/images/gall-peters_" + zoom + "_" + x + "_" + y + ".png" ); }, tileSize: new google.maps.Size(GALL_PETERS_RANGE_X, GALL_PETERS_RANGE_Y), minZoom: 0, maxZoom: 1, name: "Gall-Peters" }); // Describe the Gall-Peters projection used by these tiles. gallPetersMapType.projection = { fromLatLngToPoint: function(latLng) { const latRadians = (latLng.lat() * Math.PI) / 180; return new google.maps.Point( GALL_PETERS_RANGE_X * (0.5 + latLng.lng() / 360), GALL_PETERS_RANGE_Y * (0.5 - 0.5 * Math.sin(latRadians)) ); }, fromPointToLatLng: function(point, noWrap) { const x = point.x / GALL_PETERS_RANGE_X; const y = Math.max(0, Math.min(1, point.y / GALL_PETERS_RANGE_Y)); return new google.maps.LatLng( (Math.asin(1 - 2 * y) * 180) / Math.PI, -180 + 360 * x, noWrap ); } }; } // GeoJSON, describing the locations and names of some cities. const cities = { type: "FeatureCollection", features: [ { type: "Feature", geometry: { type: "Point", coordinates: [-87.65, 41.85] }, properties: { name: "Chicago" } }, { type: "Feature", geometry: { type: "Point", coordinates: [-149.9, 61.218] }, properties: { name: "Anchorage" } }, { type: "Feature", geometry: { type: "Point", coordinates: [-99.127, 19.427] }, properties: { name: "Mexico City" } }, { type: "Feature", geometry: { type: "Point", coordinates: [-0.126, 51.5] }, properties: { name: "London" } }, { type: "Feature", geometry: { type: "Point", coordinates: [28.045, -26.201] }, properties: { name: "Johannesburg" } }, { type: "Feature", geometry: { type: "Point", coordinates: [15.322, -4.325] }, properties: { name: "Kinshasa" } }, { type: "Feature", geometry: { type: "Point", coordinates: [151.207, -33.867] }, properties: { name: "Sydney" } }, { type: "Feature", geometry: { type: "Point", coordinates: [0, 0] }, properties: { name: "0°N 0°E" } } ] };
/* Always set the map height explicitly to define the size of the div * element that contains the map. */ #map { height: 100%; } /* Optional: Makes the sample page fill the window. */ html, body { height: 100%; margin: 0; padding: 0; } #coords { background-color: black; color: white; padding: 5px; }
<!DOCTYPE html> <html> <head> <title>Custom Map Projections</title> <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCb1xprYSpXd0q_yDsJ1W2UGhfl9_YGKU0&callback=initMap&libraries=&v=weekly" defer ></script> <!-- jsFiddle will insert css and js --> </head> <body> <div id="map"></div> <div id="coords"></div> </body> </html>