14500+ website owners are using this wordpress map plugin

Buy Now - $89

How to use create Custom Map Projections?

Introduction:

In this tutorial, we will learn with an example create a map using the Gall-Peters projection, rather than the default Mercator projection.

The Earth is a three-dimensional spherical (roughly), whereas a map is a two-dimensional flat surface. The Maps JavaScript API map, like every flat map of the Earth, is a projection of that sphere onto a flat surface. In its most basic form, a projection is a mapping of latitude/longitude values onto coordinates on the projection’s map.

Maps JavaScript API projections must implement the Projection interface. A Projection implementation must provide bi-directional mapping as well as a mapping from one coordinate system to another. That is, you must describe how to convert from Earth coordinates (LatLng objects) to the world coordinate system of the Projection class, and vice versa. Google Maps creates maps from geographic data using the Mercator projection and converts map events into geographic coordinates. This projection may be obtained by executing getProjection() on the Map (or any of the standard base MapType types.) This standard Projection will suffice for most purposes, but you can also define and use your own custom projections.

Code:

// 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.MapMouseEvent) => {
    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" },
    },
  ],
};

declare global {
  interface Window {
    initMap: () => void;
  }
}
window.initMap = initMap;
export {};

Explanation:

  • The function initMap() is created and it consists of the map properties.
  • The line, “map = new google.maps.Map(document.getElementById(“map”)”; creates a new map inside the <div> element with the help of the mentioned id which is ‘map’ as an HTMLElement.
  • const map = new google.maps.Map(
        document.getElementById("map") as HTMLElement,
    
  • The ‘centre’ attribute defines where the map should be centered with the help of the latitude and longitude coordinates.
  • center: { lat: 0, lng: 0 },
    
  • The ‘zoom’ attribute specifies the map’s zoom level.
  • zoom: 0,
    
  • mapTypeControl is set False.
  • mapTypeControl: false,
    
  • Next, the initGallPeters() is called. mapType is set to gallPeters.
  • initGallPeters();
      map.mapTypes.set("gallPeters", gallPetersMapType);
      map.setMapTypeId("gallPeters");
    
  • After, the latitude and longitude are shown under the mouse cursor.
  • const coordsDiv = document.getElementById("coords") as HTMLElement;
    
  • Map controls are set to the Top_Center.
  • map.controls[google.maps.ControlPosition.TOP_CENTER].push(coordsDiv);
    
  • The addListener() is called.
  •  map.addListener("mousemove", (event: google.maps.MapMouseEvent) => {  }
    
  • Followed by this, the markers are added to the ap.
  • Gall Peters tiles stored locally on the server. The imageMaptype is called is created.
  • Next, the tiles are wrapped horizontally and not vertically. The Gall-Peters projection are used by these tiles are described.
  •  // Wrap tiles horizontally.
          const x = ((coord.x % scale) + scale) % scale;
    
          // Don't wrap tiles vertically.
          const y = coord.y;
    
  • The GeoJSON is created describing the locations and names of some of the cities.
  • Lastly, the function is called and executed.
  • window.initMap = initMap;
    

Conclusion:

In this tutorial, we learned about how to create a map using the Gall-Peters projections rather than the default Mercator projection.

Live Example

Install Plugin Now!

This plugin is exclusively available at codecanyon.net. You'll get free updates and full support to use this plugin.