Наложение фрагментов карты, или слой фрагментов – это набор изображений, которые показываются поверх фрагментов базовой карты.
Примеры кода
В репозитории ApiDemos на сайте GitHub доступен пример, в котором показано, как работает наложение:
- TileOverlayDemoActivity – Java: как реализовать функции наложения на Java.
- TileCoordinateDemoActivity – Java: как добавить систему координат для наложений на Java.
- TileOverlayDemoActivity – Kotlin: как реализовать функции наложения на Kotlin.
- TileCoordinateDemoActivity – Kotlin: как добавить систему координат для наложений на Kotlin.
Введение
Класс TileOverlay
определяет набор изображений, которые накладываются поверх фрагментов базовой карты.
Вам потребуется создать фрагменты карты для каждого уровня масштабирования, поддержку которого вы хотите обеспечить. Если у вас достаточно фрагментов карты на нескольких уровнях масштабирования, вы можете дополнить геоданные Google для всей карты.
Наложения фрагментов карты используются, когда на карту нужно добавить большое количество изображений, покрывающих значительные географические области. Если вам нужно закрепить одно изображение на небольшом участке карты, используйте наземное наложение.
Вы также можете накладывать прозрачные фрагменты, чтобы добавлять на карту дополнительные объекты. Для этого можно использовать прозрачные изображения или программно задавать коэффициент прозрачности фрагмента.
Координаты фрагментов и уровни масштабирования
Google Maps API разбивает изображения на каждом уровне масштабирования на набор квадратных фрагментов карты, расположенных в виде сетки. Когда пользователь перетаскивает карту или меняет ее масштаб, Maps API определяет необходимые фрагменты и создает список фрагментов, которые нужно получить.
Фрагмент с координатами (0,0) всегда находится в северо-западном углу карты, при этом значения X увеличиваются в направлении с запада на восток, а значения Y – с севера на юг. Фрагменты индексируются с использованием координат X, Y относительно исходной точки.
На уровне масштабирования 0 карта всего мира отображается как один фрагмент. На каждом следующем уровне масштаб увеличивается вдвое. Следовательно, на первом уровне масштабирования карта будет отображаться в виде сетки фрагментов 2 x 2, на втором – 4 x 4, на третьем – 8 x 8 и так далее.
Например, на уровне масштабирования 2 земная поверхность делится на 16 фрагментов. Каждый фрагмент можно описать с помощью уникальной комбинации координат X, Y и масштаба:
Чтобы создать наложения, подготовьте по одному изображению для каждого фрагмента на каждом уровне масштабирования, который вы хотите поддерживать. В Google Картах при показе фрагментов используется размер 256 dp (аппаратно-независимых пикселей). Для устройств с экранами высокого разрешения рекомендуется использовать фрагменты с большим значением dpi (512 x 512 пикселей). Дополнительные сведения о поддержке экранов с различными размерами и плотностью пикселей приведены в документации для разработчиков Android.
Примечание. Уровни масштабирования, поддерживаемые камерой, зависят от различных факторов и не имеют отношения к уровням, которые будут поддерживаться вашими фрагментами.
-
GoogleMap.getMaxZoomLevel()
возвращает максимальный уровень масштабирования, доступный при текущем положении камеры. При этом учитывается используемый тип карты. Например, у спутниковых карт или карт рельефа может быть меньший максимальный уровень масштабирования, чем у фрагментов базовых карт. -
GoogleMap.getMinZoomLevel()
возвращает минимальный уровень масштабирования, который будет одинаковым для каждого места (в отличие от максимального уровня), но может различаться в зависимости от используемых устройств и размеров карт.
Как добавить наложение
Самый простой и распространенный способ создавать наложения – указать URL изображения для фрагмента карты.
UrlTileProvider
– частичная реализация класса TileProvider
, позволяющая указывать фрагменты изображений с помощью URL. При использовании этого класса необходимо, чтобы у всех изображений были одинаковые размеры.
Вам потребуется реализовать метод UrlTileProvider.getTileUrl()
, который принимает координаты фрагмента (X, Y, масштаб) и возвращает URL изображения, которое будет использовано для этого фрагмента карты. Этот метод должен возвращать значение null, если для указанных координат X, Y и масштаба нет соответствующего фрагмента. URL может указывать на веб-ресурс, ресурс Android или файл на локальном диске.
Добавьте на сервер пакет изображений, соответствующих всем сочетаниям координат X, Y и масштаба, которые должны поддерживаться. Затем добавьте накладываемый фрагмент:
- Определите класс
UrlTileProvider
, который будет предоставлять изображения фрагментов. - Переопределите метод
getTileUrl()
так, чтобы он создавал URL для каждого изображения фрагмента. - Создайте объект
TileOverlayOptions
, содержащий параметры: fadeIn
: логическое значение. Указывает, должны ли фрагменты появляться постепенно. Значение по умолчанию –true
. Если переключение между фрагментами выполняется слишком быстро, для этого параметра можно задать значение false. Информация о связи между прозрачностью и постепенным появлением приведена в разделе Как настроить прозрачность накладываемых фрагментов карты далее в этой статье.tileProvider
: объектTileProvider
, который будет использоваться для этого фрагмента.transparency
: число с плавающей запятой. Устанавливает коэффициент прозрачности накладываемых изображений. Значение должно быть в диапазоне[0.0f, 1.0f]
.0.0f
(значение по умолчанию) соответствует полной непрозрачности, а1.0f
– полной прозрачности. В разделе Как настроить прозрачность накладываемых фрагментов карты далее в этой статье приводится пример кода и описывается взаимосвязь между прозрачностью и постепенным появлением изображений.visible
: логическое значение. Указывает, является ли накладываемый фрагмент карты видимым. Если фрагмент невидимый (значениеfalse
), он не показывается на карте, но сохраняет все остальные свойства. Значение по умолчанию –true
.zIndex
: определяет порядок прорисовки фрагментов карты относительно других наложений, включая наземные наложения, круги, ломаные линии и многоугольники. Наложения с более высокими значениями Z-индекса прорисовываются выше наложений с более низкими. Порядок наложений с одинаковыми значениями z-индекса будет произвольным. По умолчанию z-индекс равен 0. Обратите внимание, что маркеры всегда располагаются поверх всех остальных наложений (независимо от значений z-индекса для этих наложений).- Чтобы добавитьна карту наложение, вызовите метод
GoogleMap.addTileOverlay()
.
Kotlin
private lateinit var map: GoogleMap var tileProvider: TileProvider = object : UrlTileProvider(256, 256) { override fun getTileUrl(x: Int, y: Int, zoom: Int): URL? { /* Define the URL pattern for the tile images */ val url = "http://my.image.server/images/$zoom/$x/$y.png" return if (!checkTileExists(x, y, zoom)) { null } else try { URL(url) } catch (e: MalformedURLException) { throw AssertionError(e) } } /* * Check that the tile server supports the requested x, y and zoom. * Complete this stub according to the tile range you support. * If you support a limited range of tiles at different zoom levels, then you * need to define the supported x, y range at each zoom level. */ private fun checkTileExists(x: Int, y: Int, zoom: Int): Boolean { val minZoom = 12 val maxZoom = 16 return zoom in minZoom..maxZoom } } val tileOverlay = map.addTileOverlay( TileOverlayOptions() .tileProvider(tileProvider) )
Java
private GoogleMap map; TileProvider tileProvider = new UrlTileProvider(256, 256) { @Override public URL getTileUrl(int x, int y, int zoom) { /* Define the URL pattern for the tile images */ String s = String.format("http://my.image.server/images/%d/%d/%d.png", zoom, x, y); if (!checkTileExists(x, y, zoom)) { return null; } try { return new URL(s); } catch (MalformedURLException e) { throw new AssertionError(e); } } /* * Check that the tile server supports the requested x, y and zoom. * Complete this stub according to the tile range you support. * If you support a limited range of tiles at different zoom levels, then you * need to define the supported x, y range at each zoom level. */ private boolean checkTileExists(int x, int y, int zoom) { int minZoom = 12; int maxZoom = 16; return (zoom >= minZoom && zoom <= maxZoom); } }; TileOverlay tileOverlay = map.addTileOverlay(new TileOverlayOptions() .tileProvider(tileProvider));
Чтобы лучше понять, как работает UrlTileProvider
, посмотрите реализацию TileOverlayDemoActivity
в примере кода, прилагаемом к SDK сервисов Google Play.
Как настроить прозрачность накладываемых фрагментов карты
Прозрачные фрагменты применяются для того, чтобы пользователи могли видеть под ними исходную карту. Для этого можно выбрать изначально прозрачные изображения или программно задать для них коэффициент прозрачности.
В следующем примере кода показано, как изменить значение прозрачности с 0.5f
на 0.0f
или обратно.
Kotlin
private var tileOverlayTransparent: TileOverlay? = null override fun onMapReady(map: GoogleMap) { tileOverlayTransparent = map.addTileOverlay( TileOverlayOptions() .tileProvider(object : UrlTileProvider(256, 256) { // ... }) .transparency(0.5f) ) } // Switch between 0.0f and 0.5f transparency. fun toggleTileOverlayTransparency() { tileOverlayTransparent?.let { it.transparency = 0.5f - it.transparency } }
Java
private TileOverlay tileOverlayTransparent; @Override public void onMapReady(GoogleMap map) { tileOverlayTransparent = map.addTileOverlay(new TileOverlayOptions() .tileProvider(new UrlTileProvider(256, 256) { // ... }) .transparency(0.5f)); } // Switch between 0.0f and 0.5f transparency. public void toggleTileOverlayTransparency() { if (tileOverlayTransparent != null) { tileOverlayTransparent.setTransparency(0.5f - tileOverlayTransparent.getTransparency()); } }
Прозрачность задается как множитель альфа-канала для изображений фрагментов. Чтобы задать прозрачность накладываемого фрагмента, создайте объект TileOverlayOptions
, где поле transparency
имеет значение в диапазоне [0.0f, 1.0f]
, как показано в примере выше. При значении 0.0f
фрагмент полностью непрозрачен, а при значении 1.0f
– полностью прозрачен. Значение по умолчанию – 0.0f
(полная непрозрачность).
Получить значение прозрачности можно с помощью метода TileOverlay.getTransparency()
, а изменить – с помощью метода TileOverlay.setTransparency()
.
Прозрачность, анимация и постепенное появление
При изменении прозрачности анимация не применяется. Параметр прозрачности используется вместе с параметром fadeIn.
Параметр fadeIn отвечает за анимацию прозрачности при загрузке фрагмента. Если установить значение прозрачности, фрагменты будут появляться постепенно – от полной прозрачности до ее установленного значения. Если изменить прозрачность во время постепенного появления, анимация будет продолжаться до нового заданного значения прозрачности.
Как удалить накладываемый фрагмент
Удалить накладываемый фрагмент карты можно с помощью метода TileOverlay.remove()
.
Kotlin
tileOverlay?.remove()
Java
tileOverlay.remove();
Как удалить устаревшие фрагменты
Если фрагменты наложения становятся неактивны, их можно принудительно обновить, вызвав метод clearTileCache()
. В результате все фрагменты в этом наложении будут перезагружены. Например, если фрагменты, предоставленные с помощью TileProvider
, изменились, нужно вызвать метод clearTileCache()
, чтобы прежние фрагменты не обрабатывались.
Kotlin
tileOverlay?.clearTileCache()
Java
tileOverlay.clearTileCache();