Calques KML et GeoRSS

Sélectionnez une plate-forme : Android iOS JavaScript

KmlLayer affiche les éléments KML et GeoRSS dans une superposition de tuiles de l'API Maps JavaScript.

Présentation

L'API Maps JavaScript est compatible avec les formats de données KML et GeoRSS pour afficher des informations géographiques. Ces formats de données sont affichés sur une carte à l'aide d'un objet KmlLayer, dont le constructeur utilise l'URL d'un fichier KML ou GeoRSS accessible publiquement.

Remarque : la classe KmlLayer qui génère les superpositions KML dans l'API Maps JavaScript récupère et analyse les fichiers KML pour le rendu via un service hébergé par Google. Par conséquent, il n'est possible d'afficher les fichiers KML que s'ils sont hébergés sur une URL accessible publiquement sans authentification.

Si vous avez besoin d'accéder à des fichiers privés, d'exercer un contrôle précis sur les caches ou d'envoyer la fenêtre d'affichage du navigateur à un serveur de données géospatiales dans un paramètre de requête, nous vous recommandons d'utiliser des calques de données plutôt que KmlLayer. Ainsi, les navigateurs de vos utilisateurs demanderont les ressources directement à votre serveur Web.

L'API Maps JavaScript convertit les données XML géographiques fournies en une représentation KML affichée sur la carte au moyen d'une superposition de tuiles de l'API Maps JavaScript. Ce fichier KML ressemble aux éléments de superposition de l'API Maps JavaScript qui vous sont familiers, et fonctionne plus ou moins comme eux. Les éléments KML <Placemark> et GeoRSS point sont affichés sous forme de repères. Par exemple, les éléments <LineString> sont affichés en tant que polylignes et les éléments <Polygon> en tant que polygones. De même, les éléments <GroundOverlay> sont affichés sous forme d'images rectangulaires sur la carte. Il est important de noter que ces objets ne sont pas des Markers, des Polylines, des Polygons ni des GroundOverlays de l'API Maps JavaScript : ils sont affichés dans un seul objet sur la carte.

Les objets KmlLayer s'affichent sur une carte une fois que leur propriété map a été définie. Vous pouvez les supprimer de la carte en appelant setMap() avec null. L'objet KmlLayer gère le rendu de ces éléments enfants en récupérant automatiquement les éléments géographiques appropriés selon les limites de la carte. Lorsque les limites sont modifiées, les éléments géographiques de la fenêtre d'affichage ouverte sont rendus automatiquement visibles.

Étant donné que les composants d'un KmlLayer sont affichés à la demande, le calque vous permet de gérer facilement le rendu de milliers de repères, de polylignes et de polygones. Notez que vous ne pouvez pas accéder directement aux objets de ces composants, bien qu'ils fournissent chacun des événements de clic renvoyant des données sur ces objets individuels.

Options de calque KML

Le constructeur KmlLayer() transmet facultativement plusieurs KmlLayerOptions :

  • map spécifie le Map sur lequel afficher le KmlLayer. Vous pouvez masquer un KmlLayer en définissant cette valeur sur null dans la méthode setMap().
  • preserveViewport indique que la carte ne doit pas être ajustée en fonction des limites du contenu du KmlLayer lors de l'affichage du calque. Par défaut, lors de l'affichage d'un KmlLayer, la carte est agrandie et positionnée de manière à afficher l'intégralité du contenu du calque.
  • suppressInfoWindows indique que les éléments géographiques cliquables dans KmlLayer ne doivent pas déclencher l'affichage d'objets InfoWindow.

En outre, une fois que KmlLayer est affiché, il contient une propriété metadata immuable contenant le nom, la description, l'extrait et l'auteur du calque dans un littéral d'objet KmlLayerMetadata. Vous pouvez inspecter ces informations à l'aide de la méthode getMetadata(). Étant donné que l'affichage des objets KmlLayer nécessite une communication asynchrone avec un serveur externe, vous devez écouter l'événement metadata_changed, qui indique que la propriété a été renseignée.

L'exemple suivant construit un KmlLayer à partir du flux GeoRSS donné :

TypeScript

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

  const georssLayer = new google.maps.KmlLayer({
    url:
      "http://api.flickr.com/services/feeds/geo/?g=322338@N20&lang=en-us&format=feed-georss",
  });
  georssLayer.setMap(map);
}

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

JavaScript

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 4,
    center: { lat: 49.496675, lng: -102.65625 },
  });
  const georssLayer = new google.maps.KmlLayer({
    url: "http://api.flickr.com/services/feeds/geo/?g=322338@N20&lang=en-us&format=feed-georss",
  });

  georssLayer.setMap(map);
}

window.initMap = initMap;

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;
}

HTML

<html>
  <head>
    <title>GeoRSS Layers</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map"></div>

    <!--
      The `defer` attribute causes the callback to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>

Essayer l'exemple

L'exemple suivant construit un KmlLayer à partir du flux KML donné :

TypeScript

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

  const ctaLayer = new google.maps.KmlLayer({
    url: "https://googlearchive.github.io/js-v2-samples/ggeoxml/cta.kml",
    map: map,
  });
}

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

JavaScript

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 11,
    center: { lat: 41.876, lng: -87.624 },
  });
  const ctaLayer = new google.maps.KmlLayer({
    url: "https://googlearchive.github.io/js-v2-samples/ggeoxml/cta.kml",
    map: map,
  });
}

window.initMap = initMap;

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;
}

HTML

<html>
  <head>
    <title>KML Layers</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="map"></div>

    <!--
      The `defer` attribute causes the callback to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>

Essayer l'exemple

Détails des éléments géographiques KML

Étant donné que le fichier KML peut inclure un grand nombre d'éléments géographiques, vous ne pouvez pas accéder à ces données directement à partir de l'objet KmlLayer. À la place, les éléments géographiques s'affichent de manière à ressembler à des superpositions d'API Maps JavaScript cliquables. Lorsque vous cliquez sur l'un d'eux, un InfoWindow contenant les informations KML <title> et <description> de l'élément géographique apparaît par défaut. En outre, un clic sur un élément géographique KML génère un KmlMouseEvent, qui transmet les informations suivantes :

  • position indique les coordonnées de latitude/longitude auxquelles l'InfoWindow doit être ancrée pour cet élément géographique KML. Cette position correspond généralement à l'emplacement du clic pour les polygones, les polylignes et les GroundOverlays, mais à l'origine réelle pour les repères.
  • pixelOffset indique le décalage par rapport à la position ci-dessus pour ancrer la "queue" du InfoWindow. Pour les objets polygonaux, ce décalage est généralement de 0,0, mais pour un repère, il est ajusté par rapport à sa hauteur.
  • featureData contient une structure JSON de KmlFeatureData.

Vous trouverez ci-dessous un exemple d'objet KmlFeatureData :

{
  author: {
    email: "nobody@google.com",
    name: "Mr Nobody",
    uri: "http://example.com"
  },
  description: "description",
  id: "id",
  infoWindowHtml: "html",
  name: "name",
  snippet: "snippet"
}

L'exemple suivant affiche le texte <Description> de l'élément géographique KML dans un <div> latéral lorsque l'utilisateur clique sur l'élément :

TypeScript

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

  const kmlLayer = new google.maps.KmlLayer({
    url: "https://raw.githubusercontent.com/googlearchive/kml-samples/gh-pages/kml/Placemark/placemark.kml",
    suppressInfoWindows: true,
    map: map,
  });

  kmlLayer.addListener("click", (kmlEvent) => {
    const text = kmlEvent.featureData.description;

    showInContentWindow(text);
  });

  function showInContentWindow(text: string) {
    const sidebar = document.getElementById("sidebar") as HTMLElement;

    sidebar.innerHTML = text;
  }
}

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

JavaScript

function initMap() {
  const map = new google.maps.Map(document.getElementById("map"), {
    zoom: 12,
    center: { lat: 37.06, lng: -95.68 },
  });
  const kmlLayer = new google.maps.KmlLayer({
    url: "https://raw.githubusercontent.com/googlearchive/kml-samples/gh-pages/kml/Placemark/placemark.kml",
    suppressInfoWindows: true,
    map: map,
  });

  kmlLayer.addListener("click", (kmlEvent) => {
    const text = kmlEvent.featureData.description;

    showInContentWindow(text);
  });

  function showInContentWindow(text) {
    const sidebar = document.getElementById("sidebar");

    sidebar.innerHTML = text;
  }
}

window.initMap = initMap;

CSS

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

#container {
  height: 100%;
  display: flex;
}

#sidebar {
  flex-basis: 15rem;
  flex-grow: 1;
  padding: 1rem;
  max-width: 30rem;
  height: 100%;
  box-sizing: border-box;
  overflow: auto;
}

#map {
  flex-basis: 0;
  flex-grow: 4;
  height: 100%;
}

HTML

<html>
  <head>
    <title>KML Feature Details</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="container">
      <div id="map"></div>
      <div id="sidebar"></div>
    </div>

    <!--
      The `defer` attribute causes the callback to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises.
      See https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=initMap&v=weekly"
      defer
    ></script>
  </body>
</html>

Essayer l'exemple

Restrictions de taille et de complexité pour le rendu KLM

L'API Maps JavaScript limite la taille et la complexité des fichiers KML chargés. Voici un récapitulatif des limites actuelles.

Remarque : Ces limites peuvent être modifiées à tout moment.

Taille maximale du fichier récupéré (KML brut, GeoRSS brut ou KMZ compressé)
3 Mo
Taille maximale du fichier KML décompressé
10 Mo
Taille maximale des fichiers image non compressés dans les fichiers KMZ
500 Ko par fichier
Nombre maximal de liens réseau
10
Nombre maximal d'éléments géographiques dans tout le document
1 000
Nombre de calques KML
Le nombre de calques KML qu'il est possible d'afficher sur une seule carte Google Maps est limité. Si vous dépassez cette limite, aucun de vos calques n'apparaîtra sur la carte et une erreur sera signalée dans la console JavaScript de votre navigateur Web. Cette limite est basée sur la combinaison entre le nombre de classes KmlLayer créées et la longueur totale de toutes les URL utilisées pour créer ces calques. Chaque nouveau KmlLayer que vous créez occupe une partie des limites du calque, plus une autre partie basée sur la longueur de l'URL à partir de laquelle le fichier KML a été chargé. Le nombre de calques que vous pouvez ajouter dépend donc de l'application. Il est en général possible de charger entre 10 et 20 calques sans atteindre cette limite. Si vous atteignez quand même la limite, utilisez un réducteur d'URL pour réduire les URL des fichiers KML. Vous pouvez également créer un seul fichier KML composé de NetworkLinks vers chacune des URL KML.

Considérations sur les performances et la mise en cache

Les serveurs de Google mettront temporairement en cache les fichiers KML pour réduire la charge sur vos serveurs. Cela améliorera également les performances pour vos utilisateurs lors des clics, des panoramiques ou des zooms sur la carte, car les segments appropriés de votre fichier KML seront représentés de manière optimale compte tenu de l'espace.

Voici nos recommandations pour accroître les performances :

  • Utilisez un tag <expires> approprié dans le code KML.

    KmlLayer n'utilisera pas d'en-têtes HTTP pour décider comment mettre en cache les fichiers KML.
  • Ne générez pas les fichiers de manière dynamique au moment de la requête.

    Générez-les plutôt avant qu'ils ne soient nécessaires et livrez-les en mode statique. Si votre serveur met beaucoup de temps à transmettre le fichier KML, le KmlLayer peut ne pas s'afficher.
  • N'essayez pas de contourner les caches, sauf si vous savez que votre fichier a réellement été mis à jour.

    Si vous contournez les caches systématiquement (par exemple, en ajoutant un nombre aléatoire ou l'heure de l'utilisateur en tant que paramètre de requête), vous pouvez facilement surcharger votre serveur si votre site devient soudainement populaire et que vous livrez des fichiers KML volumineux.

    Le cache peut également livrer des données obsolètes aux utilisateurs si l'horloge de l'utilisateur est incorrecte et si le tag <expires> n'a pas été correctement défini.

    Publiez plutôt des fichiers statiques mis à jour avec un nouveau numéro de révision distinct et utilisez du code côté serveur pour mettre à jour de façon dynamique l'URL transmise à KmlLayer avec la version actuelle.
  • Limitez les modifications de vos fichiers KML à une fois par minute.

    Si la taille de tous les fichiers dépasse 1 Mo (sans compression), limitez les modifications à une fois toutes les cinq minutes.
  • Lorsque vous utilisez un serveur de données géospatiales, évitez d'utiliser des paramètres de requête pour limiter la fenêtre d'affichage des calques.

    À la place, vous pouvez limiter la fenêtre d'affichage de la carte avec l'événement bounds_changed. Seuls des éléments géographiques pouvant être affichés automatiquement seront envoyés aux utilisateurs.

    Si votre serveur de données géospatiales contient une grande quantité de données, envisagez plutôt d'utiliser des calques de données.
  • Lorsque vous utilisez un serveur de données géospatiales, utilisez plusieurs KmlLayer (au lieu d'un seul KmlLayer avec des paramètres de requête différents) pour chaque groupe d'éléments géographiques que vous souhaitez que les utilisateurs puissent activer/désactiver.
  • Utilisez des fichiers KMZ compressés pour réduire la taille des fichiers.
  • Si vous utilisez Google Cloud Storage ou une autre solution de stockage cloud, évitez les fonctionnalités telles que les URL signées ou les jetons temporaires pour appliquer le contrôle des accès. Vous pourriez empêcher involontairement la mise en cache.
  • Réduisez la précision de tous les points à un niveau approprié.
  • Fusionnez et simplifiez la géométrie des éléments géographiques similaires tels que des polygones et des polylignes.
  • Supprimez tous les éléments ou les ressources d'image inutilisés.
  • Supprimez tous les éléments non compatibles.

Si vous devez accéder à des données privées, empêcher la mise en cache ou envoyer la fenêtre d'affichage du navigateur à un serveur de données géospatiales en tant que paramètre de requête, nous vous recommandons d'utiliser des calques de données plutôt que KmlLayer. Ainsi, les navigateurs de vos utilisateurs demanderont les ressources directement à votre serveur Web.

Éléments KML pris en charge

L'API Maps JavaScript est compatible avec les éléments KML suivants. En général, l'analyseur KML ignore silencieusement les tags XML qu'il ne comprend pas.

  • Repères
  • Icônes
  • Dossiers
  • Code HTML descriptif : remplacement d'entité via <BalloonStyle> et <text>
  • KMZ (fichier KML compressé, y compris les images jointes)
  • Polylignes et polygones
  • Styles des polylignes et des polygones, y compris la couleur, le remplissage et l'opacité
  • Liens réseau pour importer les données de façon dynamique
  • Superpositions au sol et superpositions d'écran

Le tableau suivant fournit les détails complets des éléments KML pris en charge.

Élément KML Pris en charge dans l'API ? Commentaire
<address> non
<AddressDetails> non
<Alias> N/A <Model> non pris en charge
<altitude> non
<altitudeMode> non
<atom:author> oui
<atom:link> oui
<atom:name> oui
<BalloonStyle> partiellement seul <text> pris en charge
<begin> N/A <TimeSpan> non pris en charge
<bgColor> non
<bottomFov> N/A <PhotoOverlay> non pris en charge
<Camera> non
<Change> partiellement seuls les changements de style sont pris en charge
<color> partiellement inclut #AABBGGRR et #BBGGRR ; non pris en charge dans <IconStyle>, <ScreenOverlay> et <GroundOverlay>
<colorMode> non
<cookie> non
<coordinates> oui
<Create> non
<Data> oui
<Delete> non
<description> oui Le contenu HTML est autorisé, mais il est épuré pour éviter les attaques entre navigateurs. Les remplacements d'entités au format $[dataName] ne sont pas pris en charge.
<displayMode> non
<DisplayName> non
<Document> partiellement implicitement, les enfants sont pris en charge ; sans effet en tant qu'enfant d'autres éléments géographiques
<drawOrder> non
<east> oui
<end> N/A <TimeSpan> non pris en charge
<expires> oui voir la section Résumé pour plus de détails
<ExtendedData> partiellement <Data> non typé uniquement, aucun remplacement d'entité <SimpleData> ou <Schema>, au format $[dataName] n'est pris en charge.
<extrude> non
<fill> oui
<flyToView> non
<Folder> oui
<geomColor> non obsolète
<GeometryCollection> non obsolète
<geomScale> non obsolète
<gridOrigin> N/A <PhotoOverlay> non pris en charge
<GroundOverlay> oui ne peut pas pivoter
<h> oui obsolète
<heading> oui
hint oui target=... pris en charge
<hotSpot> oui
<href> oui
<httpQuery> non
<Icon> oui ne peut pas pivoter
<IconStyle> oui
<ImagePyramid> N/A <PhotoOverlay> non pris en charge
<innerBoundaryIs> oui implicitement selon l'ordre <LinearRing>
<ItemIcon> N/A <ListStyle> non pris en charge
<key> N/A <StyleMap> non pris en charge
<kml> oui
<labelColor> non obsolète
<LabelStyle> non
<latitude> oui
<LatLonAltBox> oui
<LatLonBox> oui
<leftFov> N/A <PhotoOverlay> non pris en charge
<LinearRing> oui
<LineString> oui
<LineStyle> oui
<Link> oui
<linkDescription> non
<linkName> non
<linkSnippet> non
<listItemType> N/A <ListStyle> non pris en charge
<ListStyle> non
<Location> N/A <Model> non pris en charge
<Lod> oui
<longitude> oui
<LookAt> non
<maxAltitude> oui
<maxFadeExtent> oui
<maxHeight> N/A <PhotoOverlay> non pris en charge
<maxLodPixels> oui
<maxSessionLength> non
<maxWidth> N/A <PhotoOverlay> non pris en charge
<message> non
<Metadata> non obsolète
<minAltitude> oui
<minFadeExtent> oui
<minLodPixels> oui
<minRefreshPeriod> non <NetworkLink>
<Model> non
<MultiGeometry> partiellement affiché, mais en tant qu'éléments géographiques séparés dans le panneau de gauche
<name> oui
<near> N/A <PhotoOverlay> non pris en charge
<NetworkLink> oui  
<NetworkLinkControl> partiellement <Update> et <expires> partiellement pris en charge. L'API ignore les paramètres d'expiration dans les en-têtes HTTP, mais utilise ceux qui sont spécifiés dans le KML. En l'absence de paramètres d'expiration, ou durant l'intervalle de validité, Google Maps peut mettre cache les données récupérées sur Internet pour une durée non spécifiée. Il est possible de forcer une nouvelle récupération des données depuis Internet en renommant le document et en allant le chercher à une autre URL, ou en s'assurant que le document contient des paramètres d'expiration appropriés.
<north> oui
<open> oui
<Orientation> N/A <Model> non pris en charge
<outerBoundaryIs> oui implicitement selon l'ordre <LinearRing>
<outline> oui
<overlayXY> non
<Pair> N/A <StyleMap> non pris en charge
<phoneNumber> non
<PhotoOverlay> non
<Placemark> oui
<Point> oui
<Polygon> oui
<PolyStyle> oui
<range> oui
<refreshInterval> partiellement <Link> uniquement ; pas dans <Icon>
<refreshMode> oui En-têtes HTTP non pris en charge pour le mode "onExpire". Voir les remarques sur <Update> et <expires> plus haut.
<refreshVisibility> non
<Region> oui
<ResourceMap> N/A <Model> non pris en charge
<rightFov> N/A <PhotoOverlay> non pris en charge
<roll> N/A <Camera> et <Model> non pris en charge
<rotation> non
<rotationXY> non
<Scale> N/A <Model> non pris en charge
<scale> non
<Schema> non
<SchemaData> non
<ScreenOverlay> oui ne peut pas pivoter
<screenXY> non
<shape> N/A <PhotoOverlay> non pris en charge
<SimpleData> N/A <SchemaData> non pris en charge
<SimpleField> N/A <Schema> non pris en charge
<size> oui
<Snippet> oui
<south> oui
<state> N/A <ListStyle> non pris en charge
<Style> oui
<StyleMap> non effets de survol (surbrillance) non pris en charge
<styleUrl> N/A <StyleMap> non pris en charge
<targetHref> partiellement pris en charge dans <Update>, pas dans <Alias>
<tessellate> non
<text> oui le remplacement de $[geDirections] n'est pas pris en charge
<textColor> non
<tileSize> N/A <PhotoOverlay> non pris en charge
<tilt> non
<TimeSpan> non
<TimeStamp> non
<topFov> N/A <PhotoOverlay> non pris en charge
<Update> partiellement uniquement les changements de style, pas <Create> ou <Delete>
<Url> oui obsolète
<value> oui
<viewBoundScale> non
<viewFormat> non
<viewRefreshMode> partiellement "onStop" est pris en charge
<viewRefreshTime> oui
<ViewVolume> N/A <PhotoOverlay> non pris en charge
<visibility> partiellement oui sur <Folder> ; les repères enfants héritent de leur visibilité
<w> oui obsolète
<west> oui
<when> N/A <TimeStamp> non pris en charge
<width> oui
<x> oui obsolète
<y> oui obsolète