Слои KML и GeoRSS

Выберите платформу: Android iOS JavaScript

KmlLayer преобразует элементы KML и GeoRSS в наложения Maps JavaScript API в форме фрагмента карты.

Обзор

Maps JavaScript API поддерживает форматы данных KML и GeoRSS для отображения географической информации. Эти форматы данных отображаются на карте с помощью объекта KmlLayer, конструктор которого принимает в качестве параметра URL общедоступного файла KML или GeoRSS.

Примечание. Класс KmlLayer, создающий наложения KML в Maps JavaScript API, использует сервис Google с целью получения и синтаксического анализа KML-файлов для отрисовки. Поэтому файлы KML отображаются, только если они размещены по общедоступному URL-адресу, с которым не требуется аутентификация.

Если вам нужен доступ к закрытым файлам, точный контроль над кешем или отправка области просмотра на сервер GIS в качестве параметра запроса, рекомендуем использовать вместо KmlLayer слои данных. Благодаря этому пользователи смогут напрямую запрашивать из браузера ресурсы вашего веб-сервера.

Maps JavaScript API преобразует географические данные, предоставленные в формате XML, в KML-представление, которое показывается на карте с помощью наложенных фрагментов Maps JavaScript API. Слой KML выглядит как уже знакомые вам наложения Maps JavaScript API (и ведет себя очень похоже). Например, элемент KML <Placemark> и элемент GeoRSS point отображаются как маркеры, элементы <LineString> – как полилинии, а элементы <Polygon> – как многоугольники. Аналогично элементы <GroundOverlay> отображаются на карте как прямоугольники. Однако важно помнить, что эти элементы не являются объектами Maps JavaScript API (Markers, Polylines, Polygons или GroundOverlays) и отображаются на карте с помощью одного объекта.

Объекты KmlLayer появляются на карте, как только задается их свойство map. Убрать их с карты можно, вызвав setMap() с параметром null. Объект KmlLayer управляет отображением этих дочерних элементов, автоматически извлекая подходящие компоненты в указанных границах карты. При изменении границ прорисовка элементов автоматически выполняется в новой области просмотра.

Поскольку компоненты в KmlLayer отображаются по требованию, этот слой позволяет легко управлять показом тысяч маркеров, ломаных линий и многоугольников. Хотя каждый из них поддерживает события нажатия, возвращающие данные по конкретному объекту, вы не можете обращаться к ним напрямую.

Параметры слоя KML

Конструктор KmlLayer() может передавать несколько объектов KmlLayerOptions:

  • Свойство map указывает объект Map, на котором нужно отобразить KmlLayer. KmlLayer можно скрыть, задав для этого свойства значение null вызовом метода setMap().
  • Свойство preserveViewport указывает, что карта не должна изменяться до границ содержимого объекта KmlLayer при показе этого слоя. По умолчанию при отображении объекта KmlLayer карта изменяет масштаб и устанавливается для показа всего содержания слоя.
  • Свойство suppressInfoWindows указывает, что при нажатии на компоненты в объекте KmlLayer не должно происходить отображения InfoWindow.

Кроме того, отображенный слой KmlLayer будет содержать неизменяемое свойство metadata с названием слоя, его описанием, фрагментом и именем автора внутри литерала объекта KmlLayerMetadata. Эту информацию можно проверить с помощью метода getMetadata(). Поскольку отображение объектов KmlLayer требует асинхронного взаимодействия с внешним сервером, рекомендуем прослушать событие metadata_changed – оно указывает на заполнение свойства.

В следующем примере создается KmlLayer на основе заданного фида GeoRSS:

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 script 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>

Примеры кода

В следующем примере показано, как создать KmlLayer на основе заданного KML-фида:

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 script 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>

Примеры кода

Информация об объекте KML

Поскольку KML может включать большое количество компонентов, к ним может не быть доступа непосредственно из объекта KmlLayer. По мере отображения этих компонентов они появляются на карте как наложения Maps JavaScript API, поддерживающие нажатия мышью. По умолчанию при нажатии на любой из них вызывается окно InfoWindow, содержащее <title> и <description> данного компонента из файла KML. Также при нажатии на компонент KML создается событие KmlMouseEvent, которое передает следующую информацию:

  • position – указывает координаты широты/долготы, к которым нужно привязать InfoWindow для данного KML-компонента. Эта позиция обычно соответствует точке нажатия для многоугольников, ломаных линий и наземных наложений или координатам маркеров.
  • pixelOffset – указывает смещение относительно вышеуказанных координат position для привязки указателя ("хвоста") объекта InfoWindow. Для полигонов это смещение обычно равно 0,0, а для маркеров оно включает высоту маркера.
  • featureData – содержит структуру JSON для KmlFeatureData.

Ниже показан пример объекта KmlFeatureData:

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

В следующем примере содержимое свойства <Description> KML-компонента при нажатии на этот компонент выводится в боковом элементе <div>:

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 script 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>

Примеры кода

Ограничения размера и сложности отображения KML

Maps JavaScript API имеет ограничения по размеру и сложности загружаемых файлов KML. Ниже приведена сводная информация по действующим ограничениям.

Примечание. Эти ограничения могут быть изменены в любое время.

Максимальный размер вызываемого файла (необработанный KML, необработанный GeoRSS или сжатый KMZ)
3 МБ
Максимальный размер несжатого файла KML
10 МБ
Максимальный размер несжатого графического файла в файле KMZ
500 КБ на файл
Максимальное количество сетевых ссылок
10
Максимальное количество объектов в документе
1000
Количество слоев KML
Количество слоев KML, которое может быть показано на одной карте Google, ограничено. Если вы превысите этот лимит, ни один из ваших слоев на карте не появится, а в консоли JavaScript вашего браузера будет показано сообщение об ошибке. Лимит учитывает число созданных классов KmlLayer и общую длину всех URL-адресов, использованных для создания этих слоев. Для каждого нового слоя KmlLayer, который вы создаете, расходуется часть лимита на слои и часть лимита на URL-адреса для загрузки файлов KML (в зависимости от длины адреса). Соответственно, количество слоев, которое можно добавить, будет варьироваться от приложения к приложению. В среднем без превышения лимита можно загрузить 10–20 слоев. Если вы всё же превысили лимит, сократите длину URL-адресов KML (с помощью специального инструмента). Также можно создать файл KML со ссылками NetworkLinks на каждый из URL-адресов KML.

Производительность и кеширование

Серверы Google временно кешируют файлы KML, чтобы снизить нагрузку на ваши серверы. Это также повышает производительность на устройствах пользователей за счет компактного представления сегментов файла KML, когда пользователи нажимают на карту, перемещают и масштабируют ее.

Для повышения производительности:

  • Используйте подходящий тег <expires> в KML.

    KmlLayer не будет использовать заголовки HTTP для принятия решения о способе кеширования файлов KML.
  • Не создавайте файлы динамически во время запроса.

    Вместо этого создавайте файлы до того, как они потребуются, и передавайте их статически. Если вашему серверу требуется много времени для передачи файла KML, слой KmlLayer может не отобразиться.
  • Не пытайтесь обойти кеши, если не уверены, был ли обновлен ваш файл.

    Постоянный обход кешей (например, путем добавления случайного числа или времени пользователя в качестве параметра запроса) может привести к перегрузке ваших серверов, если посещаемость резко вырастет и сайту придется передавать файлы KML в большом количестве.

    Это также может привести к передаче пользователям устаревших данных из кеша, если значение времени на устройстве пользователя неверно или тег <expires> задан некорректно.

    Публикуйте обновленные статические файлы с новым дискретным номером версии и используйте серверный код для динамического обновления URL-адреса, передаваемого вместе с этой версией в слой KmlLayer.
  • Ограничьте частоту внесения изменений в файлы KML до одного раза в минуту.

    Если размер всех файлов превышает 1 МБ (без сжатия), ограничьте частоту изменений одним разом в 5 минут.
  • При использовании сервера геопространственных данных избегайте параметров запроса, которые ограничивают области просмотра слоев.

    Вместо этого ограничивайте область просмотра карты с помощью события bounds_changed. Пользователям будут отправляться только функции, которые отображаются автоматически.

    Если данных на вашем сервере GIS слишком много, рассмотрите возможность использования слоев данных.
  • На сервере геопространственных данных используйте разные слои KmlLayer для каждой группы функций, которые хотите разрешить включать/отключать своим пользователям (не используйте один слой KmlLayer с разными параметрами запроса).
  • Сжимайте файлы KMZ.
  • Если вы работаете с Google Cloud Storage или другим облачным хранилищем, избегайте использования подписанных URL, временных токенов и других функций контроля доступа. Они могут непреднамеренно помешать кешированию.
  • Уменьшите точность всех точек до приемлемой.
  • Объединяйте полигоны, полилинии и упрощайте геометрию этих и других объектов.
  • Удаляйте все неиспользуемые элементы и источники изображений.
  • Удаляйте все неподдерживаемые элементы.

Если вам нужен доступ к закрытым данным, предотвращение кеширования или отправка области просмотра на сервер GIS в качестве параметра запроса, рекомендуем использовать вместо KmlLayer слои данных. Так пользователи будут напрямую запрашивать из браузера ресурсы с вашего веб-сервера.

Поддерживаемые элементы KML

Ниже перечислены элементы KML, которые поддерживает Maps JavaScript API. Синтаксический анализатор KML, как правило, просто игнорирует теги XML, которые не понимает.

  • Метки.
  • Значки.
  • Папки.
  • Описательный HTML — замена объекта с помощью <BalloonStyle> и <text>.
  • KMZ (сжатый KML, включая прикрепленные изображения).
  • Ломаные линии и многоугольники.
  • Стили ломаных линий и многоугольников, включая цвет, заливку и прозрачность.
  • Сетевые ссылки для динамического импорта данных.
  • Наземные наложения и экранные наложения.

В следующей таблице приведены все подробности о поддерживаемых элементах KML.

Элемент KML Поддержка в API Комментарий
<address> Нет
<AddressDetails> Нет
<Alias> Элементы <Model> не поддерживаются.
<altitude> Нет
<altitudeMode> Нет
<atom:author> Да
<atom:link> Да
<atom:name> Да
<BalloonStyle> Частично Поддерживается только элемент <text>.
<begin> Элементы <TimeSpan> не поддерживаются.
<bgColor> Нет
<bottomFov> Элементы <PhotoOverlay> не поддерживаются.
<Camera> Нет
<Change> Частично Поддерживаются только изменения стилей.
<color> Частично Включает значения #AABBGGRR и #BBGGRR; не поддерживается внутри элементов <IconStyle>, <ScreenOverlay> и <GroundOverlay>.
<colorMode> Нет
<cookie> Нет
<coordinates> Да
<Create> Нет
<Data> Да
<Delete> Нет
<description> Да Содержимое HTML допустимо, но проверяется с целью защиты от кроссбраузерных атак. Замена объектов формы $[dataName] не поддерживается.
<displayMode> Нет
<displayName> Нет
<Document> Частично Косвенно поддерживаются дочерние элементы. Дочерние элементы других объектов не действуют.
<drawOrder> Нет
<east> Да
<end> Элементы <TimeSpan> не поддерживаются.
<expires> Да Дополнительные сведения приведены в разделе "Сводка".
<ExtendedData> Частично Только нетипизированные элементы <Data> (не <SimpleData> или <Schema>). Замена объектов формы $[dataName] не поддерживается.
<extrude> Нет
<fill> Да
<flyToView> Нет
<Folder> Да
<geomColor> Нет Устаревший
<GeometryCollection> Нет Устаревший
<geomScale> Нет Устаревший
<gridOrigin> Элементы <PhotoOverlay> не поддерживаются.
<GroundOverlay> Да Элемент нельзя вращать.
<h> Да Устаревший
<heading> Да
hint Да Поддерживается target=...
<hotSpot> Да
<href> Да
<httpQuery> Нет
<Icon> Да Элемент нельзя вращать.
<IconStyle> Да
<ImagePyramid> Элементы <PhotoOverlay> не поддерживаются.
<innerBoundaryIs> Да Косвенно поддерживается в сочетании с элементом <LinearRing>.
<ItemIcon> Элементы <ListStyle> не поддерживаются.
<key> Элементы <StyleMap> не поддерживаются.
<kml> Да
<labelColor> Нет поддержка прекращена
<LabelStyle> Нет
<latitude> Да
<LatLonAltBox> Да
<LatLonBox> Да
<leftFov> Элементы <PhotoOverlay> не поддерживаются.
<LinearRing> Да
<LineString> Да
<LineStyle> Да
<Link> Да
<linkDescription> Нет
<linkName> Нет
<linkSnippet> Нет
<listItemType> Элементы <ListStyle> не поддерживаются.
<ListStyle> Нет
<Location> Элементы <Model> не поддерживаются.
<Lod> Да
<longitude> Да
<LookAt> Нет
<maxAltitude> Да
<maxFadeExtent> Да
<maxHeight> Элементы <PhotoOverlay> не поддерживаются.
<maxLodPixels> Да
<maxSessionLength> Нет
<maxWidth> Элементы <PhotoOverlay> не поддерживаются.
<message> Нет
<Metadata> Нет поддержка прекращена
<minAltitude> Да
<minFadeExtent> Да
<minLodPixels> Да
<minRefreshPeriod> Нет <NetworkLink>
<Model> Нет
<MultiGeometry> Частично Прорисовывается, но отображается как отдельный объект на панели слева.
<name> Да
<near> Элементы <PhotoOverlay> не поддерживаются.
<NetworkLink> Да  
<NetworkLinkControl> Частично Частично поддерживаются элементы <Update> и <expires>. API игнорирует срок действия в HTTP-заголовках и использует те, что указаны в KML. Когда срок действия не указан или период достоверности ещё не истек, Google Карты могут кешировать данные, полученные из интернета, и хранить их неопределенно долго. Принудительное обновление этих данных можно инициировать, переименовав документ, запросив его с помощью другого URL-адреса или явным образом прописав окончание его срока действия.
<north> Да
<open> Да
<Orientation> Элементы <Model> не поддерживаются.
<outerBoundaryIs> Да Косвенно поддерживается в сочетании с элементом <LinearRing>.
<outline> Да
<overlayXY> Нет
<Pair> Элементы <StyleMap> не поддерживаются.
<phoneNumber> Нет
<PhotoOverlay> Нет
<Placemark> Да
<Point> Да
<Polygon> Да
<PolyStyle> Да
<range> Да
<refreshInterval> Частично Только внутри элемента <Link> (не <Icon>).
<refreshMode> Да HTTP-заголовки не поддерживаются в режиме "onExpire". См. примечание для <Update> и <expires> выше.
<refreshVisibility> Нет
<Region> Да
<ResourceMap> Элементы <Model> не поддерживаются.
<rightFov> Элементы <PhotoOverlay> не поддерживаются.
<roll> Элементы <Camera> и <Model> не поддерживаются.
<rotation> Нет
<rotationXY> Нет
<Scale> Элементы <Model> не поддерживаются.
<scale> Нет
<Schema> Нет
<SchemaData> Нет
<ScreenOverlay> Да Элемент нельзя вращать.
<screenXY> Нет
<shape> Элементы <PhotoOverlay> не поддерживаются.
<SimpleData> Элементы <SchemaData> не поддерживаются.
<SimpleField> Элементы <Schema> не поддерживаются.
<size> Да
<Snippet> Да
<south> Да
<state> Элементы <ListStyle> не поддерживаются.
<Style> Да
<StyleMap> Нет Эффекты выделения не поддерживаются
<styleUrl> Элементы <StyleMap> не поддерживаются.
<targetHref> Частично Только внутри элемента <Update> (не <Alias>).
<tessellate> Нет
<text> Да Замена $[geDirections] не поддерживается.
<textColor> Нет
<tileSize> Элементы <PhotoOverlay> не поддерживаются.
<tilt> Нет
<TimeSpan> Нет
<TimeStamp> Нет
<topFov> Элементы <PhotoOverlay> не поддерживаются.
<Update> Частично Только изменения стилей (<Create> или <Delete> не поддерживаются).
<Url> Да Устаревший
<value> Да
<viewBoundScale> Нет
<viewFormat> Нет
<viewRefreshMode> Частично Поддерживается значение onStop.
<viewRefreshTime> Да
<ViewVolume> Элементы <PhotoOverlay> не поддерживаются.
<visibility> Частично Поддерживается внутри элемента <Folder>. Дочерние метки наследуют настройки видимости.
<w> Да Устаревший
<west> Да
<when> Элементы <TimeStamp> не поддерживаются.
<width> Да
<x> Да Устаревший
<y> Да Устаревший