Types de carte

Sélectionnez une plate-forme : Android iOS JavaScript

Ce document décrit les types de cartes que vous pouvez afficher à l'aide de l'API Maps JavaScript. L'API utilise un objet MapType pour stocker des informations sur ces cartes. Un MapType est une interface qui définit l'affichage et l'utilisation des tuiles de carte, ainsi que la traduction des systèmes de coordonnées de l'écran en coordonnées mondiales (sur la carte). Chaque MapType doit contenir plusieurs méthodes pour traiter la récupération et la suppression des tuiles, ainsi que les propriétés qui définissent son comportement visuel.

Le fonctionnement interne des types de carte dans l'API Maps JavaScript est un sujet complexe. La plupart des développeurs peuvent utiliser les types de carte basiques indiqués ci-dessous. Toutefois, vous pouvez également modifier la présentation des types de carte existants en utilisant des cartes stylisées ou en définissant vos propres tuiles de carte à l'aide des types de carte personnalisés. Lorsque vous fournissez des types de carte personnalisés, vous devez comprendre comment modifier le registre des types de carte.

Types de carte basiques

Il existe quatre types de carte disponibles dans l'API Maps JavaScript. Outre les tuiles de carte routière colorées qui vous sont familières, l'API Maps JavaScript est également compatible avec d'autres types de carte.

Les types de carte suivants sont disponibles dans l'API Maps JavaScript :

  • roadmap affiche la carte routière par défaut. Il s'agit du type de carte par défaut.
  • satellite affiche les images satellites de Google Earth.
  • hybrid affiche une combinaison de vues normales et de vues satellite.
  • terrain affiche une carte physique basée sur les informations de relief.

Vous modifiez le type de carte utilisé par Map en définissant sa propriété mapTypeId, soit dans le constructeur en définissant l'objet Map options, soit en appelant la méthode setMapTypeId(). La propriété mapTypeID est définie par défaut sur roadmap.

Définir mapTypeId lors de la construction :

var myLatlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions = {
  zoom: 8,
  center: myLatlng,
  mapTypeId: 'satellite'
};
var map = new google.maps.Map(document.getElementById('map'),
    mapOptions);

Modifier mapTypeId de manière dynamique :

map.setMapTypeId('terrain');

Notez que vous ne définissez pas directement le type de la carte. Au lieu de cela, vous référencez un MapType à l'aide d'un identifiant dans le mapTypeId. L'API Maps JavaScript utilise un registre de types de carte, expliqué ci-dessous, pour gérer ces références.

Images à 45°

L'API Maps JavaScript prend en charge les images à 45° spéciales pour certains lieux. Ces images haute résolution fournissent des vues en perspective vers chacun des quatre points cardinaux (nord, sud, est et ouest). Elles sont également disponibles à des niveaux de zoom supérieurs pour les types de carte pris en charge.

L'image suivante montre une vue à 45° de New York :

Les types de carte satellite et hybrid prennent en charge les images à 45° à des niveaux de zoom élevés (12 ou plus) lorsqu'elles sont disponibles. Si l'utilisateur zoome sur un lieu où de telles images sont disponibles, ces types de carte modifient automatiquement leurs vues de la manière suivante :

  • L'image satellite ou hybride est remplacée par une image offrant une perspective à 45° centrée sur le point géographique sélectionné. Par défaut, ces vues sont orientées vers le nord. Si l'utilisateur fait un zoom arrière, l'image satellite ou hybride par défaut s'affiche à nouveau. Le comportement varie en fonction du niveau de zoom et de la valeur de tilt :
    • Entre les niveaux de zoom 12 et 18, la carte de base plongeante (0°) s'affiche par défaut, sauf si tilt est défini sur 45.
    • À un niveau de zoom supérieur ou égal à 18, la carte de base à 45° s'affiche, sauf si tilt est défini sur 0.
  • La commande de rotation devient visible. La commande de rotation fournit des options permettant à l'utilisateur d'activer/désactiver l'inclinaison et de faire pivoter la vue par incréments de 90° dans les deux sens. Pour masquer la commande de rotation, définissez rotateControl sur false.

Un zoom arrière sur un type de carte affichant une image à 45° supprime les modifications apportées à la vue et rétablit les types de carte d'origine.

Activer et désactiver les images à 45°

Vous pouvez désactiver les images à 45° en appelant setTilt(0) sur l'objet Map. Pour activer les images à 45° pour les types de carte compatibles, appelez setTilt(45). La méthode getTilt() de Map reflète toujours le tilt actuellement affiché sur la carte. Si vous définissez un tilt sur une carte, puis que vous supprimez ce tilt par la suite (en faisant un zoom arrière, par exemple), la méthode getTilt() de la carte renverra 0.

Important : Les images à 45° ne sont compatibles qu'avec les cartes matricielles, et non avec les cartes vectorielles.

L'exemple suivant affiche une vue à 45° de la ville de New York :

TypeScript

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      center: { lat: 40.76, lng: -73.983 },
      zoom: 15,
      mapTypeId: "satellite",
    }
  );

  map.setTilt(45);
}

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

JavaScript

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 40.76, lng: -73.983 },
    zoom: 15,
    mapTypeId: "satellite",
  });

  map.setTilt(45);
}

window.initMap = initMap;
Voir un exemple

Essayer avec un exemple

Voir un exemple

Faire pivoter des images à 45°

Les images à 45° consistent en fait en plusieurs images pour chaque point cardinal (nord, sud, est, ouest). Une fois que les images à 45° sont affichées sur votre carte, vous pouvez les orienter vers l'un des points cardinaux en appelant setHeading() sur l'objet Map et en transmettant une valeur numérique exprimée en degrés à partir du nord.

L'exemple suivant montre une carte aérienne qui pivote automatiquement toutes les trois secondes lorsque l'utilisateur clique sur le bouton :

TypeScript

let map: google.maps.Map;

function initMap(): void {
  map = new google.maps.Map(document.getElementById("map") as HTMLElement, {
    center: { lat: 40.76, lng: -73.983 },
    zoom: 15,
    mapTypeId: "satellite",
    heading: 90,
    tilt: 45,
  });

  // add listener to button
  document.getElementById("rotate")!.addEventListener("click", autoRotate);
}

function rotate90(): void {
  const heading = map.getHeading() || 0;

  map.setHeading(heading + 90);
}

function autoRotate(): void {
  // Determine if we're showing aerial imagery.
  if (map.getTilt() !== 0) {
    window.setInterval(rotate90, 3000);
  }
}

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

JavaScript

let map;

function initMap() {
  map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 40.76, lng: -73.983 },
    zoom: 15,
    mapTypeId: "satellite",
    heading: 90,
    tilt: 45,
  });
  // add listener to button
  document.getElementById("rotate").addEventListener("click", autoRotate);
}

function rotate90() {
  const heading = map.getHeading() || 0;

  map.setHeading(heading + 90);
}

function autoRotate() {
  // Determine if we're showing aerial imagery.
  if (map.getTilt() !== 0) {
    window.setInterval(rotate90, 3000);
  }
}

window.initMap = initMap;
Voir un exemple

Essayer avec un exemple

Voir un exemple

Modifier le registre des types de carte

Le mapTypeId d'une carte est un identifiant de chaîne permettant d'associer un MapType à une valeur unique. Chaque objet Map gère un MapTypeRegistry qui contient un ensemble de plusieurs MapType disponibles pour cette carte. Ce registre est utilisé pour sélectionner les types de carte disponibles dans la commande MapType de Map, par exemple.

Vous n'accédez pas directement au registre des types de carte, mais vous le modifiez en y ajoutant des types de carte personnalisés que vous associez à l'identifiant de chaîne de votre choix. Vous ne pouvez pas modifier les types de carte basiques (mais vous pouvez les supprimer de la carte en modifiant l'apparence des mapTypeControlOptions associées à la carte).

Le code suivant définit deux types de carte à afficher seulement dans les mapTypeControlOptions de la carte et modifie le registre pour ajouter l'association avec cet identifiant à l'implémentation effective de l'interface MapType.

// Modify the control to only display two maptypes, the
// default ROADMAP and the custom 'mymap'.
// Note that because this is an association, we
// don't need to modify the MapTypeRegistry beforehand.

var MY_MAPTYPE_ID = 'mymaps';

var mapOptions = {
  zoom: 12,
  center: brooklyn,
  mapTypeControlOptions: {
     mapTypeIds: ['roadmap', MY_MAPTYPE_ID]
  },
  mapTypeId: MY_MAPTYPE_ID
};

// Create our map. This creation will implicitly create a
// map type registry.
map = new google.maps.Map(document.getElementById('map'),
    mapOptions);

// Create your custom map type using your own code.
// (See below.)
var myMapType = new MyMapType();

// Set the registry to associate 'mymap' with the
// custom map type we created, and set the map to
// show that map type.
map.mapTypes.set(MY_MAPTYPE_ID, myMapType);

Cartes stylisées

Le StyledMapType permet de personnaliser la présentation des cartes de base Google standards en modifiant l'apparence de certains éléments tels que les routes, les parcs et les zones construites dans un style différent de celui du type de carte par défaut.

Pour en savoir plus sur StyledMapType, consultez le guide des cartes stylisées.

Types de carte personnalisés

L'API Maps JavaScript prend en charge l'affichage et la gestion des types de carte personnalisés, ce qui vous permet d'implémenter vos propres images de carte ou superpositions de tuiles.

Plusieurs types de cartes peuvent être implémentés dans l'API Maps JavaScript :

  • Les ensembles de tuiles standards sont composés d'images qui constituent collectivement des cartes complètes. Ces ensembles de tuiles sont également appelés les types de carte de base. Ces types de carte fonctionnent et se comportent comme les types de carte par défaut existants : roadmap, satellite, hybrid et terrain. Vous pouvez ajouter votre type de carte personnalisé au tableau mapTypes d'une carte pour que l'UI de l'API Maps JavaScript puisse traiter votre type de carte personnalisé comme un type de carte standard (en l'incluant dans la commande MapType, par exemple).
  • Les superpositions de tuiles d'images s'affichent au-dessus des types de carte de base existants. En règle générale, ces types de carte servent à améliorer un type de carte existant en affichant des informations supplémentaires. Ils sont souvent limités à certains points géographiques et/ou niveaux de zoom spécifiques. Notez que ces tuiles peuvent être transparentes, ce qui vous permet d'ajouter des composants aux cartes existantes.
  • Les types de carte autres que des images vous permettent de manipuler l'affichage des informations d'une carte à son niveau le plus fondamental.

Chacune de ces options repose sur la création d'une classe qui implémente l'interface MapType. De plus, la classe ImageMapType intègre un comportement qui simplifie la création des types de carte d'images.

Interface MapType

Avant de créer des classes qui implémentent MapType, il est important de comprendre comment Google Maps détermine les coordonnées et décide quelles parties de la carte afficher. Vous devez implémenter une logique similaire pour tous les types de carte de base ou de superposition. Consultez le guide sur les coordonnées de carte et de tuile.

Les types de cartes personnalisés doivent implémenter l'interface MapType. Cette interface spécifie certaines propriétés et méthodes qui permettent à l'API d'initier des requêtes ciblant votre ou vos types de cartes lorsque l'API détermine qu'elle doit afficher des tuiles de carte dans la fenêtre d'affichage actuelle et avec le niveau de zoom sélectionné. Vous traitez ces requêtes pour décider quelle tuile charger.

Remarque : Vous pouvez créer votre propre classe pour implémenter cette interface. Si vous disposez d'images compatibles, vous pouvez également utiliser la classe ImageMapType, qui implémente déjà cette interface.

Pour implémenter l'interface MapType, vous devez définir et renseigner les propriétés suivantes :

  • tileSize (obligatoire) spécifie la taille de la tuile (de type google.maps.Size). Les tailles doivent être rectangulaires, mais pas carrées.
  • maxZoom (obligatoire) spécifie le niveau de zoom maximal auquel les tuiles doivent être affichées pour ce type de carte.
  • minZoom (facultatif) spécifie le niveau de zoom minimal auquel les tuiles doivent être affichées pour ce type de carte. La valeur par défaut est 0 (aucun niveau de zoom minimal n'est défini).
  • name (facultatif) spécifie le nom de ce type de carte. Cette propriété n'est nécessaire que si vous souhaitez que ce type de carte soit sélectionnable au sein d'une commande MapType. (Voir Ajouter des commandes MapType ci-dessous).
  • alt (facultatif) spécifie le texte de substitution pour ce type de carte, affiché lorsque l'utilisateur pointe sur l'élément. Cette propriété n'est nécessaire que si vous souhaitez que ce type de carte soit sélectionnable au sein d'une commande MapType. (Voir Ajouter des commandes MapType ci-dessous).

En outre, les classes qui implémentent l'interface MapType doivent utiliser les méthodes suivantes :

  • getTile() (obligatoire) est appelé chaque fois que l'API détermine que la carte doit afficher de nouvelles tuiles pour la fenêtre d'affichage donnée. Cette méthode getTile() doit avoir la signature suivante :

    getTile(tileCoord:Point,zoom:number,ownerDocument:Document):Node

    L'API détermine s'il faut appeler getTile() en fonction des propriétés tileSize, minZoom et maxZoom du MapType, et en fonction de la fenêtre d'affichage et du niveau de zoom. Pour cette méthode, le gestionnaire doit renvoyer un élément HTML basé sur les coordonnées et sur le niveau de zoom transmis, ainsi que sur l'élément DOM auquel ajouter l'image de la tuile.

  • releaseTile() (facultatif) est appelé chaque fois que l'API détermine que la carte doit supprimer une tuile lorsqu'elle n'est plus visible. Cette méthode doit avoir la signature suivante :

    releaseTile(tile:Node)

    En général, vous devez supprimer tout élément joint aux tuiles au moment de leur ajout à la carte. Par exemple, si vous avez joint des écouteurs d'événement aux superpositions de tuiles de la carte, c'est à ce moment que vous devez les supprimer.

La méthode getTile() est le principal contrôleur permettant de déterminer les tuiles à charger dans une fenêtre d'affichage donnée.

Types de carte de base

Les types de carte que vous construisez de cette manière peuvent être soit autonomes, soit combinés à d'autres types de carte en tant que superpositions. Les types de carte autonomes sont appelés types de carte de base. Si vous souhaitez que l'API traite ces MapType personnalisés de la même façon que les autres types de carte de base existants (ROADMAP, TERRAIN, etc.), ajoutez votre MapType personnalisé à la propriété mapTypes de Map. Cette propriété est de type MapTypeRegistry.

Le code suivant crée un MapType de base pour afficher les coordonnées des tuiles d'une carte et trace le contour des tuiles :

TypeScript

/*
 * This demo demonstrates how to replace default map tiles with custom imagery.
 * In this case, the CoordMapType displays gray tiles annotated with the tile
 * coordinates.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */

class CoordMapType {
  tileSize: google.maps.Size;
  maxZoom = 19;
  name = "Tile #s";
  alt = "Tile Coordinate Map Type";

  constructor(tileSize: google.maps.Size) {
    this.tileSize = tileSize;
  }

  getTile(
    coord: google.maps.Point,
    zoom: number,
    ownerDocument: Document
  ): HTMLElement {
    const div = ownerDocument.createElement("div");

    div.innerHTML = String(coord);
    div.style.width = this.tileSize.width + "px";
    div.style.height = this.tileSize.height + "px";
    div.style.fontSize = "10";
    div.style.borderStyle = "solid";
    div.style.borderWidth = "1px";
    div.style.borderColor = "#AAAAAA";
    div.style.backgroundColor = "#E5E3DF";
    return div;
  }

  releaseTile(tile: HTMLElement): void {}
}

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 10,
      center: { lat: 41.85, lng: -87.65 },
      streetViewControl: false,
      mapTypeId: "coordinate",
      mapTypeControlOptions: {
        mapTypeIds: ["coordinate", "roadmap"],
        style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
      },
    }
  );

  map.addListener("maptypeid_changed", () => {
    const showStreetViewControl =
      (map.getMapTypeId() as string) !== "coordinate";

    map.setOptions({
      streetViewControl: showStreetViewControl,
    });
  });

  // Now attach the coordinate map type to the map's registry.
  map.mapTypes.set(
    "coordinate",
    new CoordMapType(new google.maps.Size(256, 256))
  );
}

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

JavaScript

/*
 * This demo demonstrates how to replace default map tiles with custom imagery.
 * In this case, the CoordMapType displays gray tiles annotated with the tile
 * coordinates.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */
class CoordMapType {
  tileSize;
  maxZoom = 19;
  name = "Tile #s";
  alt = "Tile Coordinate Map Type";
  constructor(tileSize) {
    this.tileSize = tileSize;
  }
  getTile(coord, zoom, ownerDocument) {
    const div = ownerDocument.createElement("div");

    div.innerHTML = String(coord);
    div.style.width = this.tileSize.width + "px";
    div.style.height = this.tileSize.height + "px";
    div.style.fontSize = "10";
    div.style.borderStyle = "solid";
    div.style.borderWidth = "1px";
    div.style.borderColor = "#AAAAAA";
    div.style.backgroundColor = "#E5E3DF";
    return div;
  }
  releaseTile(tile) {}
}

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 10,
    center: { lat: 41.85, lng: -87.65 },
    streetViewControl: false,
    mapTypeId: "coordinate",
    mapTypeControlOptions: {
      mapTypeIds: ["coordinate", "roadmap"],
      style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
    },
  });

  map.addListener("maptypeid_changed", () => {
    const showStreetViewControl = map.getMapTypeId() !== "coordinate";

    map.setOptions({
      streetViewControl: showStreetViewControl,
    });
  });
  // Now attach the coordinate map type to the map's registry.
  map.mapTypes.set(
    "coordinate",
    new CoordMapType(new google.maps.Size(256, 256)),
  );
}

window.initMap = initMap;
Voir un exemple

Essayer avec un exemple

Types de cartes de superposition

Certains types de carte sont conçus pour fonctionner au-dessus d'autres types de carte existants. De tels types de carte peuvent avoir des calques transparents indiquant des points d'intérêt ou affichant des données supplémentaires à l'utilisateur.

Dans ce cas, vous ne devez pas considérer ce type de carte comme une entité distincte, mais comme une superposition. Pour ce faire, vous pouvez ajouter le type de carte à un MapType existant directement à l'aide de la propriété overlayMapTypes de Map. Cette propriété contient un MVCArray de plusieurs MapType. Tous les types de carte (de base et de superposition) sont affichés dans le calque mapPane. Les types de carte de superposition s'affichent par-dessus la carte de base à laquelle ils sont associés, dans l'ordre dans lequel ils apparaissent dans le tableau Map.overlayMapTypes (les superpositions avec des valeurs d'index plus élevées sont affichées devant celles avec des valeurs d'index plus faibles).

L'exemple suivant est identique au précédent, mais nous avons créé un MapType de superposition de tuiles sur le type de carte ROADMAP :

TypeScript

/*
 * This demo illustrates the coordinate system used to display map tiles in the
 * API.
 *
 * Tiles in Google Maps are numbered from the same origin as that for
 * pixels. For Google's implementation of the Mercator projection, the origin
 * tile is always at the northwest corner of the map, with x values increasing
 * from west to east and y values increasing from north to south.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */

class CoordMapType implements google.maps.MapType {
  tileSize: google.maps.Size;
  alt: string|null = null;
  maxZoom: number = 17;
  minZoom: number = 0;
  name: string|null = null;
  projection: google.maps.Projection|null = null;
  radius: number = 6378137;

  constructor(tileSize: google.maps.Size) {
    this.tileSize = tileSize;
  }
  getTile(
    coord: google.maps.Point,
    zoom: number,
    ownerDocument: Document
  ): HTMLElement {
    const div = ownerDocument.createElement("div");

    div.innerHTML = String(coord);
    div.style.width = this.tileSize.width + "px";
    div.style.height = this.tileSize.height + "px";
    div.style.fontSize = "10";
    div.style.borderStyle = "solid";
    div.style.borderWidth = "1px";
    div.style.borderColor = "#AAAAAA";
    return div;
  }
  releaseTile(tile: Element): void {}
}

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      zoom: 10,
      center: { lat: 41.85, lng: -87.65 },
    }
  );

  // Insert this overlay map type as the first overlay map type at
  // position 0. Note that all overlay map types appear on top of
  // their parent base map.
  const coordMapType = new CoordMapType(new google.maps.Size(256, 256))
  map.overlayMapTypes.insertAt(
    0,
    coordMapType
  );
}

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

JavaScript

/*
 * This demo illustrates the coordinate system used to display map tiles in the
 * API.
 *
 * Tiles in Google Maps are numbered from the same origin as that for
 * pixels. For Google's implementation of the Mercator projection, the origin
 * tile is always at the northwest corner of the map, with x values increasing
 * from west to east and y values increasing from north to south.
 *
 * Try panning and zooming the map to see how the coordinates change.
 */
class CoordMapType {
  tileSize;
  alt = null;
  maxZoom = 17;
  minZoom = 0;
  name = null;
  projection = null;
  radius = 6378137;
  constructor(tileSize) {
    this.tileSize = tileSize;
  }
  getTile(coord, zoom, ownerDocument) {
    const div = ownerDocument.createElement("div");

    div.innerHTML = String(coord);
    div.style.width = this.tileSize.width + "px";
    div.style.height = this.tileSize.height + "px";
    div.style.fontSize = "10";
    div.style.borderStyle = "solid";
    div.style.borderWidth = "1px";
    div.style.borderColor = "#AAAAAA";
    return div;
  }
  releaseTile(tile) {}
}

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 10,
    center: { lat: 41.85, lng: -87.65 },
  });
  // Insert this overlay map type as the first overlay map type at
  // position 0. Note that all overlay map types appear on top of
  // their parent base map.
  const coordMapType = new CoordMapType(new google.maps.Size(256, 256));

  map.overlayMapTypes.insertAt(0, coordMapType);
}

window.initMap = initMap;
Voir un exemple

Essayer avec un exemple

Types de cartes d'image

Implémenter un MapType pour agir en tant que type de carte de base peut être long et laborieux. L'API fournit une classe spéciale qui implémente l'interface MapType pour les types de carte les plus courants, à savoir ceux constitués de tuiles elles-mêmes composées de fichiers image uniques.

Cette classe, ImageMapType, est construite à l'aide d'une spécification d'objet ImageMapTypeOptions définissant les propriétés obligatoires suivantes :

  • tileSize (obligatoire) spécifie la taille de la tuile (de type google.maps.Size). Les tailles doivent être rectangulaires, mais pas carrées.
  • getTileUrl (obligatoire) spécifie la fonction, généralement fournie sous forme de littéral de fonction intégrée, pour traiter la sélection de la tuile d'image appropriée en fonction des coordonnées mondiales et du niveau de zoom fournis.

Le code suivant implémente un ImageMapType basique à l'aide des tuiles de lune de Google. Cet exemple utilise une fonction de normalisation pour que les tuiles se répètent le long de l'axe x, mais pas de l'axe y de votre carte.

TypeScript

function initMap(): void {
  const map = new google.maps.Map(
    document.getElementById("map") as HTMLElement,
    {
      center: { lat: 0, lng: 0 },
      zoom: 1,
      streetViewControl: false,
      mapTypeControlOptions: {
        mapTypeIds: ["moon"],
      },
    }
  );

  const moonMapType = new google.maps.ImageMapType({
    getTileUrl: function (coord, zoom): string {
      const normalizedCoord = getNormalizedCoord(coord, zoom);

      if (!normalizedCoord) {
        return "";
      }

      const bound = Math.pow(2, zoom);
      return (
        "https://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw" +
        "/" +
        zoom +
        "/" +
        normalizedCoord.x +
        "/" +
        (bound - normalizedCoord.y - 1) +
        ".jpg"
      );
    },
    tileSize: new google.maps.Size(256, 256),
    maxZoom: 9,
    minZoom: 0,
    // @ts-ignore TODO 'radius' does not exist in type 'ImageMapTypeOptions'
    radius: 1738000,
    name: "Moon",
  });

  map.mapTypes.set("moon", moonMapType);
  map.setMapTypeId("moon");
}

// Normalizes the coords that tiles repeat across the x axis (horizontally)
// like the standard Google map tiles.
function getNormalizedCoord(coord, zoom) {
  const y = coord.y;
  let 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
  const 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 };
}

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

JavaScript

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: 0, lng: 0 },
    zoom: 1,
    streetViewControl: false,
    mapTypeControlOptions: {
      mapTypeIds: ["moon"],
    },
  });
  const moonMapType = new google.maps.ImageMapType({
    getTileUrl: function (coord, zoom) {
      const normalizedCoord = getNormalizedCoord(coord, zoom);

      if (!normalizedCoord) {
        return "";
      }

      const bound = Math.pow(2, zoom);
      return (
        "https://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw" +
        "/" +
        zoom +
        "/" +
        normalizedCoord.x +
        "/" +
        (bound - normalizedCoord.y - 1) +
        ".jpg"
      );
    },
    tileSize: new google.maps.Size(256, 256),
    maxZoom: 9,
    minZoom: 0,
    // @ts-ignore TODO 'radius' does not exist in type 'ImageMapTypeOptions'
    radius: 1738000,
    name: "Moon",
  });

  map.mapTypes.set("moon", moonMapType);
  map.setMapTypeId("moon");
}

// Normalizes the coords that tiles repeat across the x axis (horizontally)
// like the standard Google map tiles.
function getNormalizedCoord(coord, zoom) {
  const y = coord.y;
  let 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
  const 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 };
}

window.initMap = initMap;
Voir un exemple

Essayer avec un exemple

Projections

La Terre est une sphère (ou presque) tridimensionnelle, tandis qu'une carte est une surface plane bidimensionnelle. Comme toute carte plane de la Terre, la carte que vous voyez dans l'API Maps JavaScript est une projection de cette sphère sur une surface plane. Pour faire simple, une projection consiste à transformer des valeurs de latitude/longitude en coordonnées sur la carte de la projection.

Les projections dans l'API Maps JavaScript doivent implémenter l'interface Projection. Une implémentation de Projection doit fournir non seulement un mappage d'un système de coordonnées à un autre, mais aussi un mappage bidirectionnel. Autrement dit, vous devez définir comment traduire des coordonnées Earth (objets LatLng) vers le système de coordonnées mondiales de la classe Projection et inversement. Google Maps utilise la projection de Mercator pour créer des cartes à partir de données géographiques et convertir les événements sur la carte en coordonnées géographiques. Vous pouvez obtenir cette projection en appelant getProjection() sur le Map (ou sur n'importe quel type MapType standard de base). Pour la plupart des utilisations, cette Projection standard suffit. Toutefois, vous pouvez également définir et utiliser vos propres projections personnalisées.

Implémenter une projection

Lorsque vous implémentez une projection personnalisée, vous devez définir plusieurs éléments :

  • La formule pour traduire des coordonnées de latitude et de longitude en un plan cartésien, et inversement. (L'interface Projection ne prend en charge que les transformations en coordonnées rectilignes.)
  • La taille des tuiles de base. Toutes les tuiles doivent être rectangulaires.
  • La "taille du monde" de la carte au moyen des tuiles de base définies au niveau de zoom 0. Notez que pour les cartes qui consistent en une seule tuile au niveau de zoom 0, la taille du monde et la taille de la tuile de base sont identiques.

Transformer des coordonnées en projections

Chaque projection fournit deux méthodes pour convertir des coordonnées géographiques en coordonnées mondiales :

  • La méthode Projection.fromLatLngToPoint() convertit une valeur LatLng en coordonnées mondiales. Cette méthode sert à positionner des superpositions sur la carte (et à positionner la carte elle-même).
  • La méthode Projection.fromPointToLatLng() convertit une coordonnée mondiale en valeur LatLng. Cette méthode sert à convertir des événements tels que des clics sur la carte en coordonnées géographiques.

Google Maps suppose que les projections sont rectilignes.

En règle générale, vous pouvez utiliser une projection dans deux cas : pour créer une carte du monde ou pour créer une carte d'une zone locale. Dans le premier cas, vous devez veiller à ce que votre projection soit également rectiligne et normale à toutes les longitudes. Certaines projections (en particulier les projections coniques) peuvent être "localement normales" (par exemple, au point nord), mais dévier du nord géographique, par exemple, lorsque la carte est positionnée de plus en plus loin de sa longitude de référence. Vous pouvez utiliser une telle projection localement, mais sachez qu'elle manque naturellement de précision et que les erreurs de transformation sont de plus en plus visibles à mesure que vous vous éloignez de la longitude de référence à partir de laquelle vous déviez.

Sélectionner le type de tuile dans les projections

Les projections ne sont pas seulement utiles pour déterminer la position des points géographiques ou des superpositions, elles permettent également de positionner les tuiles de carte elles-mêmes. L'API Maps JavaScript effectue le rendu des cartes de base en utilisant une interface MapType, qui doit déclarer à la fois une propriété projectionpour identifier la projection de la carte et une méthode getTile() pour récupérer les tuiles de carte en fonction des valeurs des coordonnées des tuiles. Les coordonnées des tuiles sont basées à la fois sur la taille de vos tuiles basiques (qui doivent être rectangulaires) et la taille "du monde" de votre carte, c'est-à-dire la taille en pixels de votre carte mondiale au niveau de zoom 0. (Pour les cartes qui consistent en une seule tuile au niveau de zoom 0, la taille de la tuile et la taille du monde sont identiques.)

Vous définissez la taille de la tuile de base dans la propriété tileSize de votre MapType. Vous définissez implicitement la taille du monde dans les méthodes fromLatLngToPoint() et fromPointToLatLng() de votre projection.

Étant donné que la sélection des images dépend des valeurs transmises, il s'avère utile de nommer les images qui peuvent être sélectionnées par programmation en fonction de ces valeurs. Par exemple, en utilisant le format map_zoom_tileX_tileY.png.

L'exemple suivant définit un ImageMapType à l'aide de la projection de Gall-Peters :

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.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") as string,
      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;

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" },
    },
  ],
};

window.initMap = initMap;
Voir un exemple

Essayer avec un exemple