Маркеры

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

Маркеры обозначают отдельные местоположения на карте. Маркеры можно настраивать, например менять их цвета или значки. Информационные окна могут содержать дополнительные сведения о маркерах.

Примеры кода

Хранилище ApiDemos на сайте GitHub содержит пример, где демонстрируются различные свойства маркера:

Kotlin

  • MapWithMarker: простая карта с маркером. О том, как ее добавить, читайте в руководстве.
  • MarkerDemoActivity: использование маркеров на карте, включая настройки и прослушиватели.

Java

  • MapWithMarker: простая карта с маркером. О том, как ее добавить, читайте в руководстве.
  • MarkerDemoActivity: использование маркеров на карте, включая настройки и прослушиватели.

Введение

Маркеры указывают местоположения на карте. По умолчанию используется стандартный значок, знакомый вам по работе с Google Картами. С помощью API можно изменить цвет значка, его изображение или точку привязки. Маркеры (объекты Marker) добавляются на карту с помощью метода GoogleMap.addMarker(markerOptions).

Маркеры – это интерактивные элементы. По умолчанию они принимают события click и часто используются с прослушивателями событий для вывода информационных окон. Если для свойства маркера draggable задать значение true, пользователь сможет изменять положение маркера на карте. Функция перетаскивания активируется долгим нажатием на маркер.

По умолчанию, когда пользователь касается маркера, в правом нижнем углу карты появляется панель инструментов для быстрого доступа к мобильному приложению "Google Карты". Эту панель можно отключить. Дополнительные сведения вы можете найти в руководстве по элементам управления.

Начало работы с маркерами

В этом эпизоде Maps Live рассказывается об основах добавления маркеров на карту с использованием Maps SDK for Android.

Добавление маркера

В следующем примере показано, как добавить маркер на карту. Маркер создается в точке с координатами -33.852,151.211 (Сидней, Австралия), а при нажатии на него в информационном окне появляется строка Marker in Sydney (Маркер в Сиднее).

Kotlin



override fun onMapReady(googleMap: GoogleMap) {
    // Add a marker in Sydney, Australia,
    // and move the map's camera to the same location.
    val sydney = LatLng(-33.852, 151.211)
    googleMap.addMarker(
        MarkerOptions()
            .position(sydney)
            .title("Marker in Sydney")
    )
    googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
}

      

Java


@Override
public void onMapReady(GoogleMap googleMap) {
    // Add a marker in Sydney, Australia,
    // and move the map's camera to the same location.
    LatLng sydney = new LatLng(-33.852, 151.211);
    googleMap.addMarker(new MarkerOptions()
        .position(sydney)
        .title("Marker in Sydney"));
    googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}

      

Как показать дополнительную информацию о маркере

Когда пользователь касается маркера на карте, должна выводиться информация о месте или местоположении. Дополнительные сведения вы можете найти в руководстве по информационным окнам.

Связь данных с маркером

В маркере можно сохранить объект произвольных данных, используя метод Marker.setTag(), и извлечь этот объект данных с помощью метода Marker.getTag(). В приведенном ниже примере кода показано, как с помощью тегов подсчитать количество кликов по маркеру.

Kotlin



/**
 * A demo class that stores and retrieves data objects with each marker.
 */
class MarkerDemoActivity : AppCompatActivity(),
    OnMarkerClickListener, OnMapReadyCallback {
    private val PERTH = LatLng(-31.952854, 115.857342)
    private val SYDNEY = LatLng(-33.87365, 151.20689)
    private val BRISBANE = LatLng(-27.47093, 153.0235)

    private var markerPerth: Marker? = null
    private var markerSydney: Marker? = null
    private var markerBrisbane: Marker? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_markers)
        val mapFragment =
            supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
        mapFragment!!.getMapAsync(this)
    }

    /** Called when the map is ready.  */
    override fun onMapReady(map: GoogleMap) {
        // Add some markers to the map, and add a data object to each marker.
        markerPerth = map.addMarker(
            MarkerOptions()
                .position(PERTH)
                .title("Perth")
        )
        markerPerth?.tag = 0
        markerSydney = map.addMarker(
            MarkerOptions()
                .position(SYDNEY)
                .title("Sydney")
        )
        markerSydney?.tag = 0
        markerBrisbane = map.addMarker(
            MarkerOptions()
                .position(BRISBANE)
                .title("Brisbane")
        )
        markerBrisbane?.tag = 0

        // Set a listener for marker click.
        map.setOnMarkerClickListener(this)
    }

    /** Called when the user clicks a marker.  */
    override fun onMarkerClick(marker: Marker): Boolean {

        // Retrieve the data from the marker.
        val clickCount = marker.tag as? Int

        // Check if a click count was set, then display the click count.
        clickCount?.let {
            val newClickCount = it + 1
            marker.tag = newClickCount
            Toast.makeText(
                this,
                "${marker.title} has been clicked $newClickCount times.",
                Toast.LENGTH_SHORT
            ).show()
        }

        // Return false to indicate that we have not consumed the event and that we wish
        // for the default behavior to occur (which is for the camera to move such that the
        // marker is centered and for the marker's info window to open, if it has one).
        return false
    }
}

      

Java


/**
 * A demo class that stores and retrieves data objects with each marker.
 */
public class MarkerDemoActivity extends AppCompatActivity implements
    GoogleMap.OnMarkerClickListener,
    OnMapReadyCallback {

    private final LatLng PERTH = new LatLng(-31.952854, 115.857342);
    private final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
    private final LatLng BRISBANE = new LatLng(-27.47093, 153.0235);

    private Marker markerPerth;
    private Marker markerSydney;
    private Marker markerBrisbane;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_markers);
        SupportMapFragment mapFragment =
            (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    /** Called when the map is ready. */
    @Override
    public void onMapReady(GoogleMap map) {
        // Add some markers to the map, and add a data object to each marker.
        markerPerth = map.addMarker(new MarkerOptions()
            .position(PERTH)
            .title("Perth"));
        markerPerth.setTag(0);

        markerSydney = map.addMarker(new MarkerOptions()
            .position(SYDNEY)
            .title("Sydney"));
        markerSydney.setTag(0);

        markerBrisbane = map.addMarker(new MarkerOptions()
            .position(BRISBANE)
            .title("Brisbane"));
        markerBrisbane.setTag(0);

        // Set a listener for marker click.
        map.setOnMarkerClickListener(this);
    }

    /** Called when the user clicks a marker. */
    @Override
    public boolean onMarkerClick(final Marker marker) {

        // Retrieve the data from the marker.
        Integer clickCount = (Integer) marker.getTag();

        // Check if a click count was set, then display the click count.
        if (clickCount != null) {
            clickCount = clickCount + 1;
            marker.setTag(clickCount);
            Toast.makeText(this,
                marker.getTitle() +
                    " has been clicked " + clickCount + " times.",
                Toast.LENGTH_SHORT).show();
        }

        // Return false to indicate that we have not consumed the event and that we wish
        // for the default behavior to occur (which is for the camera to move such that the
        // marker is centered and for the marker's info window to open, if it has one).
        return false;
    }
}

      

Примеры случаев, когда вам может понадобиться сохранить или получить данные с помощью маркеров:

  • Вы хотите, чтобы нажатия на маркеры разных типов обрабатывались в приложении по-разному. Для этого сохраните в маркере объект String с указанием типа.
  • Вы работаете с интерфейсом к системе, в которой имеются уникальные идентификаторы записей и каждый маркер соответствует одной записи в этой системе.
  • В данных маркера записан приоритет, который определяет значение параметра z-index для этого маркера.

Как сделать маркер перетаскиваемым

Чтобы маркер можно было перемещать после его добавления на карту, задайте для свойства draggable значение true. Перетаскивание маркера активируется долгим нажатием. Маркер останется в той точке, где пользователь уберет палец с экрана.

По умолчанию возможность перетаскивания маркеров отключена. Вы должны включить эту функцию с помощью метода MarkerOptions.draggable(boolean) до добавления маркера на карту или же с помощью метода Marker.setDraggable(boolean), когда маркер уже добавлен. Вы можете прослушивать события перетаскивания для маркера.

В приведенном ниже фрагменте кода перетаскиваемый маркер устанавливается для города Перт, Австралия.

Kotlin



val perthLocation = LatLng(-31.90, 115.86)
val perth = map.addMarker(
    MarkerOptions()
        .position(perthLocation)
        .draggable(true)
)

      

Java


final LatLng perthLocation = new LatLng(-31.90, 115.86);
Marker perth = map.addMarker(
    new MarkerOptions()
        .position(perthLocation)
        .draggable(true));

      

Как настроить маркер

В этом видеоролике рассказывается, как использовать маркеры для визуального представления различных мест на карте.

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

Настроить маркер можно с помощью следующих свойств:

Position (Положение; обязательно)
Значение параметра LatLng для положения маркера на карте. Это единственное обязательное свойство объекта Marker.
Anchor (Привязка)
Точка на изображении, которое будет размещено в месте, указанном параметром маркера LatLng (широта и долгота). По умолчанию устанавливается по центру в нижней части изображения.
Alpha (Альфа-канал)
Свойство, определяющее прозрачность маркера. Значение по умолчанию – 1.0.
Title (Заголовок)
Строка, которая отображается в информационном окне, когда пользователь касается маркера.
Snippet (Фрагмент)
Дополнительный текст, отображаемый под названием.
Icon (Значок)
Картинка в битовом формате, которая отображается вместо значка по умолчанию.
Draggable (Перетаскиваемость)
Задайте значение true, если хотите, чтобы пользователи могли перетаскивать значок. Значение по умолчанию – false.
Visible (Видимость)
Измените значение этого свойства на false, чтобы сделать маркер невидимым. Значение по умолчанию – true.
Flat или Billboard (свойства ориентации)
По умолчанию используется афишная ориентация маркера (Billboard), которая рассчитывается относительно экрана устройства, а не карты и при масштабировании, повороте и наклоне камеры остается неизменной. Однако вы можете настроить и плоскую ориентацию (Flat), при которой маркер лежит на земной поверхности, вращается и наклоняется вместе с картой. При масштабировании размер плоского маркера, так же как и афишного, остается неизменным.
Rotation (Вращение)
Поворот маркера по часовой стрелке в градусах. Для плоских маркеров направление по умолчанию может изменяться. По умолчанию плоский маркер направлен на север. Остальные маркеры по умолчанию расположены перпендикулярно земной поверхности и при вращении обращены в сторону камеры.

Ниже представлен код, который позволяет создать простой маркер со стандартным значком.

Kotlin



val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
)

      

Java


final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(
    new MarkerOptions()
        .position(melbourneLocation));

      

Как настроить цвет маркера

Чтобы изменить цвет стандартного изображения маркера, необходимо передать объект BitmapDescriptor в метод icon(). Вы можете использовать набор предварительно установленных цветов в объекте BitmapDescriptorFactory или задать конкретный цвет маркера с помощью метода BitmapDescriptorFactory.defaultMarker(float hue). Параметр hue (тон) должен содержать значение от 0 до 360, представляющее собой точку на цветовом круге.

Kotlin



val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
)

      

Java


final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(
    new MarkerOptions()
        .position(melbourneLocation)
        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));

      

Как настроить прозрачность маркера

Для изменения прозрачности маркера можно использовать метод MarkerOptions.alpha(). Непрозрачность следует указывать как число от 0.0 до 1.0 с плавающей точкой, где 0 – полная прозрачность, а 1 – полная непрозрачность.

Kotlin



val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
        .alpha(0.7f)
)

      

Java


final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(new MarkerOptions()
    .position(melbourneLocation)
    .alpha(0.7f));

      

Как настроить значок маркера

Значок маркера по умолчанию можно заменить любым другим изображением. Собственные значки всегда задаются в виде объекта BitmapDescriptor и определяются с через один из методов в классе BitmapDescriptorFactory.

fromAsset(String assetName)
Создает собственный маркер, используя название битового изображения в каталоге ресурсов.
fromBitmap(Bitmap image)
Создает собственный маркер из битового изображения.
fromFile(String fileName)
Создает собственный значок, используя название битового файла, который хранится во внутренней памяти устройства.
fromPath(String absolutePath)
Создает собственный маркер, используя абсолютный путь к битовому файлу.
fromResource(int resourceId)
Создает собственный маркер, используя идентификатор ресурса битового изображения.

Приведенный ниже фрагмент создает маркер с пользовательским значком.

Kotlin



val melbourneLocation = LatLng(-37.813, 144.962)
val melbourne = map.addMarker(
    MarkerOptions()
        .position(melbourneLocation)
        .title("Melbourne")
        .snippet("Population: 4,137,400")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow))
)

      

Java


final LatLng melbourneLocation = new LatLng(-37.813, 144.962);
Marker melbourne = map.addMarker(
    new MarkerOptions()
        .position(melbourneLocation)
        .title("Melbourne")
        .snippet("Population: 4,137,400")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));

      

Как создать плоский маркер

Положение значка маркера обычно рассчитывается относительно экрана. Масштабирование, повороты и наклоны камеры не влияют на его ориентацию. Однако можно сделать так, чтобы значок лежал на земной поверхности, вращался и наклонялся вместе с картой. Размер плоского маркера не меняется при приближении и отдалении.

Чтобы изменить ориентацию маркера, установите для свойства flat значение true.

Kotlin



val perthLocation = LatLng(-31.90, 115.86)
val perth = map.addMarker(
    MarkerOptions()
        .position(perthLocation)
        .flat(true)
)

      

Java


final LatLng perthLocation = new LatLng(-31.90, 115.86);
Marker perth = map.addMarker(
    new MarkerOptions()
        .position(perthLocation)
        .flat(true));

      

Как повернуть маркер

Маркер можно вращать вокруг точки привязки с помощью метода Marker.setRotation(). Значение измеряется относительно исходного положения в градусах по часовой стрелке. Если маркер плоский, он по умолчанию ориентирован на север. Остальные маркеры по умолчанию расположены перпендикулярно земной поверхности и при вращении обращены в сторону камеры.

В приведенном ниже примере маркер поворачивается на 90°. Если установить для опорной точки значения 0.5,0.5, маркер будет вращаться вокруг своего центра, а не вокруг основания.

Kotlin



val perthLocation = LatLng(-31.90, 115.86)
val perth = map.addMarker(
    MarkerOptions()
        .position(perthLocation)
        .anchor(0.5f, 0.5f)
        .rotation(90.0f)
)

      

Java


final LatLng perthLocation = new LatLng(-31.90, 115.86);
Marker perth = map.addMarker(
    new MarkerOptions()
        .position(perthLocation)
        .anchor(0.5f,0.5f)
        .rotation(90.0f));

      

Z-индекс маркера

Z-индекс определяет порядок наложения маркера относительно других маркеров на карте. Маркеры с более высоким Z-индексом показываются поверх маркеров с меньшим. Значение по умолчанию – 0.

Задайте Z-индекс для объекта параметров маркера, вызвав метод MarkerOptions.zIndex(), как показано в следующем примере кода:

Kotlin



map.addMarker(
    MarkerOptions()
        .position(LatLng(10.0, 10.0))
        .title("Marker z1")
        .zIndex(1.0f)
)

      

Java


map.addMarker(new MarkerOptions()
    .position(new LatLng(10, 10))
    .title("Marker z1")
    .zIndex(1.0f));

      

Чтобы узнать Z-индекс, используйте метод Marker.getZIndex(), а чтобы изменить – Marker.setZIndex().

Маркеры всегда показываются поверх фрагментов карты и других не являющихся маркерами наложений (наземных наложений, ломаных линий, многоугольников и других фигур). Это не зависит от Z-индекса других наложений. Фактически у маркеров свое пространство Z-индексов, отдельное от Z-индексов других наложений.

Читайте ниже о влиянии Z-индекса на события клика.

Обработка событий маркера

Maps API позволяет прослушивать события маркера и реагировать на них. Для этого необходимо назначить объекту GoogleMap, к которому относятся маркеры, соответствующий прослушиватель. Если для одного из маркеров карты возникает событие, соответствующий объект Marker, передаваемый в виде параметра, выполняет обратный вызов прослушивателя. Чтобы сопоставить этот объект Marker с вашей собственной ссылкой на Marker, используйте метод equals(), а не оператор ==.

Можно прослушивать следующие события:

События кликов по маркеру

Чтобы отслеживать события кликов по маркеру, используйте прослушиватель OnMarkerClickListener. Чтобы добавить его на карту, вызовите метод GoogleMap.setOnMarkerClickListener(OnMarkerClickListener). Когда пользователь нажимает на маркер, выполняется вызов onMarkerClick(Marker), а маркер передается в виде аргумента. Этот метод возвращает логическое значение, указывающее, было ли событие принято (т. е. нужно ли подавлять поведение по умолчанию). Если возвращается значение false, поведение по умолчанию выполняется параллельно с персонализированным. Поведение по умолчанию для события клика по маркеру – отображение его информационного окна (если оно доступно) и перемещение камеры таким образом, чтобы маркер находился в центре карты.

Влияние z-индекса на события кликов:

  • Когда пользователь нажимает на кластер маркеров, событие клика назначается маркеру с самым большим Z-индексом.
  • Клик не может запускать более одного события. Другими словами, клик не передается маркерам или иным оверлеям с меньшими значениями Z-индекса.
  • После того как пользователь в первый раз нажмет на кластер маркеров, каждое последующее нажатие по очереди передается следующему маркеру. При этом учитываются прежде всего значения Z-индекса, а затем – расстояние до точки клика.
  • Если пользователь нажимает на карту достаточно далеко от кластера, API пересчитывает кластер и переопределяет состояние цикла кликов, запуская его с начала.
  • Событие клика переходит от кластера маркеров на другие фигуры и оверлеи, а затем цикл начинается снова.
  • Можно считать, что у маркеров и других фигур (ломаных линий, многоугольников, кругов, наземных оверлеев) разные группы значений Z-индекса – независимо от того, какие Z-индексы заданы для этих других фигур. Если несколько маркеров, наложений или фигур перекрывают друг друга, то клики сначала по очереди передаются по кластеру маркеров, а затем вызываются для других кликабельных наложений или фигур в зависимости от их Z-индекса.

События перетаскивания маркера

Для отслеживания перетаскивания можно использовать прослушиватель OnMarkerDragListener. Чтобы добавить его на карту, вызовите метод GoogleMap.setOnMarkerDragListener. Функция перетаскивания активируется долгим нажатием на маркер. Маркер останется в той точке, где пользователь уберет палец с экрана. В начале перетаскивания вызывается метод onMarkerDragStart(Marker), во время перетаскивания – onMarkerDrag(Marker) (он вызывается непрерывно), а по окончании – onMarkerDragEnd(Marker). Положение маркера можно в любое время запросить с помощью метода Marker.getPosition().