Объекты карты

MapKit SDK позволяет отображать на карте объекты. Все объекты карты настраиваемые: вы можете создавать уникальные пользовательские сценарии с учетом потребностей разработчиков.

Метки

Добавьте пользовательские метки изображения на карту с помощью метода MapObjectCollection.addPlacemark из поля Map.getMapObjects.

Метод создает экземпляр метки на карте, который можно сконфигурировать: указать Point с координатами для метки и иконку с помощью класса ImageProvider, для инициализации которого используются ассеты

val placemark = map.mapObjects.addPlacemark().apply {
    geometry = Point(59.935493, 30.327392)
    setIcon(ImageProvider.fromResource(this, R.drawable.ic_pin))
}

С помощью приведенного выше кода создается экземпляр класса PlacemarkMapObject, который расширяет интерфейс MapObject.

Интерфейс MapObject представляет каждый видимый объект на карте. Существует несколько способов настройки объектов карты: изменение видимости, разрешение перетаскивания, изменение z-индекса, настройка обработчика событий касания или перетаскивания и многое другое.

Подробнее об этом можно почитать в разделе MapObject.

Настройка текста

Вы можете создавать текстовые надписи рядом с метками. Для этого используйте метод PlacemarkMapObject.setText.

Чтобы изменить внешний вид меток, включая их размер, цвет и положение текста относительно значка, используйте метод TextStyle.

placemark.setText(
    "Special place",
    TextStyle(/* args */)
)

Стили значков

Вы можете настроить представление значков меток с помощью класса IconStyle. Он позволяет изменять положение привязки, размер, тип поворота, z-индекс, кликабельные области, видимость и плоскость по отношению к карте.

placemark.setIconStyle(
    IconStyle().apply {
        anchor = PointF(0.5f, 1.0f)
        scale = 0.6f
        zIndex = 10
    }
)

Составные значки

Объедините несколько значков, чтобы создать составной.

  1. Создайте значок по умолчанию с помощью MapObjectCollection.addPlacemark.

  2. Используйте PlacemarkMapObject.useCompositeIcon, чтобы создать составной значок.

  3. Используйте CompositeIcon.setIcon, чтобы добавить новый значок к составному значку.

Полный пример кода для создания составного значка:

val placemark = map.mapObjects.addPlacemark().apply {
    geometry = Point(59.935493, 30.327392)
    setText(
        "Special place",
        TextStyle().apply {
            size = 10f
            placement = Placement.RIGHT
            offset = 5f
        },
    )
}

placemark.useCompositeIcon().apply {
    setIcon(
        "pin",
        ImageProvider.fromResource(this@Activity, R.drawable.ic_dollar_pin),
        IconStyle().apply {
            anchor = PointF(0.5f, 1.0f)
            scale = 0.9f
        }
    )
    setIcon(
        "point",
        ImageProvider.fromResource(this@Activity, R.drawable.ic_circle),
        IconStyle().apply {
            anchor = PointF(0.5f, 0.5f)
            flat = true
            scale = 0.05f
        }
    )
}

Результат:

Пример составного значка

Анимированные метки

Вы можете создать анимированную метку из анимированного PNG-файла.

  1. Создайте метку с помощью MapObjectCollection.addPlacemark.

    val placemark = map.mapObjects.addPlacemark() {
        geometry = Point(59.935493, 30.327392)
    }
    
  2. Используйте метод PlacemarkMapObject.useAnimation для создания объекта анимации. Задать ресурс анимации можно при помощи экземпляра AnimatedImageProvider.

    val animation = placemark.useAnimation().apply {
        setIcon(AnimatedImageProvider.fromAsset(this, "animation.png"))
    }
    
  3. Запустите анимацию, управляя ею с помощью объекта PlacemarkAnimation.

    animation.play()
    

Коллекции меток

Коллекции меток используются для группировки нескольких меток в новую коллекцию вложенных объектов карты.

  1. Чтобы создать коллекцию вложенных объектов карты, используйте метод MapObjectCollection.addCollection.

    val pinsCollection = map.mapObjects.addCollection()
    
  2. Теперь вы можете использовать новую коллекцию pinsCollection для отображения меток и других объектов карты.

    val points = listOf(
        Point(59.935493, 30.327392),
        Point(59.938185, 30.32808),
        Point(59.937376, 30.33621),
        Point(59.934517, 30.335059),
    )
    
    val imageProvider = ImageProvider.fromResource(this, R.drawable.ic_pin)
    
    points.forEach { point ->
        pinsCollection.addPlacemark().apply {
            geometry = point
            setIcon(imageProvider)
        }
    }
    

    Примечание

    Используйте один экземпляр ImageProvider, если вам нужно отобразить несколько похожих меток. Это будет эффективнее, чем создавать новый экземпляр для каждой метки.

    Как это выглядит после добавления меток в коллекцию новых объектов карты:

    Карта с коллекцией меток

После создания коллекции pinCollection вы можете добавить в нее пины так же, как и для объектов Map.getMapObjects, поскольку они имеют тот же тип MapObjectCollection.

Примечание

Интерфейс MapObjectCollection расширяет MapObject, поэтому допускается создавать вложенные коллекции и добавлять их в другие.

Все методы, имеющие интерфейс MapObject, также доступны в MapObjectCollection.

Вы можете итерироваться по элементам MapObjectCollection, используя метод BaseMapObjectCollection.traverse.

Геометрии

MapKit SDK позволяет рисовать на карте примитивные геометрические объекты, такие как полигоны, полилинии и круги. Все они настраиваемые и реализуют интерфейс MapObject.

Полигоны

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

  1. Начните с создания экземпляра Polygon.

    val points = listOf(
        Point(59.935493, 30.327392),
        Point(59.938185, 30.32808),
        Point(59.937376, 30.33621),
        Point(59.934517, 30.335059),
    )
    val polygon = Polygon(LinearRing(points), emptyList())
    
  2. Используйте метод MapObjectCollection.addPolygon для создания полигонального объекта карты.

    val polygonMapObject = map.mapObjects.addPolygon(polygon)
    

    После завершения сборки вы увидите полигон в стиле по умолчанию:

    Карта с полигоном по умолчанию

  3. Задайте внутренние точки при создании полигона, чтобы исключить часть внутри него.

    val points = listOf(
        Point(59.935493, 30.327392),
        Point(59.938185, 30.32808),
        Point(59.937376, 30.33621),
        Point(59.934517, 30.335059),
    )
    val innerPoints = listOf(
        Point(59.937487, 30.330034),
        Point(59.936688, 30.33127),
        Point(59.937116, 30.33328),
        Point(59.937704, 30.331842),
    )
    val polygon = Polygon(LinearRing(points), listOf(LinearRing(innerPoints)))
    

    Полигон с внутренними точками:

    Карта с полигоном с использованием внутренних точек

  4. Измените цвет заливки и обводки по умолчанию, используя созданный экземпляр PolygonMapObject.

    polygonMapObject.apply {
        strokeWidth = 1.5f
        strokeColor = ContextCompat.getColor(this@Activity, R.color.olive)
        fillColor = ContextCompat.getColor(this@Activity, R.color.green)
    }
    

    Карта со стилизованным полигоном

Подробнее про настройку полигонов см. в разделе PolygonMapObject.

Полилинии

Полилинии часто используются для отображения маршрутов и траекторий.

  1. Создайте экземпляр Polyline с искомой геометрией и добавьте на карту объект полилинейной карты с помощью метода MapObjectCollection.addPolyline.

    val points = listOf(
        Point(59.935493, 30.327392),
        Point(59.938185, 30.32808),
        Point(59.937376, 30.33621),
        Point(59.934517, 30.335059),
    )
    val polyline = Polyline(points)
    
    val polylineObject = map.mapObjects.addPolyline(polyline)
    
  2. Настройте стили полилиний, используя переменную PolylineMapObject.

    polylineObject.apply {
        strokeWidth = 5f
        setStrokeColor(ContextCompat.getColor(this@Activity, R.color.gray))
        outlineWidth = 1f
        outlineColor = ContextCompat.getColor(this@Activity, R.color.black)
    }
    

    Результат после добавления полилинии на карту:

    Карта с добавленной полилинией

Подробнее об этом можно почитать в разделе PolylineMapObject.

Круги

Круги используются для отображения круглых областей.

  1. Создайте экземпляр Circle с искомой геометрией: центральной точкой и радиусом в метрах.

    val circle = Circle(
        Point(59.935493, 30.327392),
        400f
    )
    
  2. С помощью метода MapObjectCollection.addCircle добавьте на карту объект круга.

    map.mapObjects.addCircle(circle).apply {
        strokeWidth = 2f
        strokeColor = ContextCompat.getColor(this, R.color.red)
        fillColor = ContextCompat.getColor(this, R.color.red_alpha)
    }
    

    Результат после добавления круга на карту:

    Карта с кругом

Подробнее о том, как настроить круговой объект карты, можно почитать в разделе CircleMapObject.

Кластеры

Кластеризованные коллекции используются для отображения нескольких меток.

  1. Начните с создания ClusterListener с одним методом ClusterListener.onClusterAdded, который управляет внешним видом кластера на карте.

    val clusterListener = ClusterListener { cluster ->
        cluster.appearance.setView(
            ViewProvider(
                ClusterView(this).apply {
                    setText("${cluster.placemarks.size}")
                }
            )
        )
    }
    

    Свойство Cluster.getAppearance возвращает объект PlacemarkMapObject. В нашем примере мы используем метод PlacemarkMapObject.setView, чтобы изменить внешний вид кластера.

    ClusterView — это определяемый пользователем класс. Чтобы узнать, как он реализован, посмотрите код в нашем репозитории на GitHub.

  2. Создайте новую вложенную коллекцию с помощью метода MapObjectCollection.addClusterizedPlacemarkCollection.

    val clusterizedCollection = map.mapObjects.addClusterizedPlacemarkCollection(clusterListener)
    
  3. Добавьте несколько меток в новый clusterizedCollection.

    val points = listOf(
        Point(59.935493, 30.327392),
        Point(59.938185, 30.32808),
        Point(59.937376, 30.33621),
        Point(59.934517, 30.335059),
    )
    val imageProvider = ImageProvider.fromResource(this, R.drawable.ic_pin)
    
    points.forEach { point ->
        clusterizedCollection.addPlacemark().apply {
            geometry = point
            setIcon(imageProvider)
        }
    }
    
  4. Вызовите метод ClusterizedPlacemarkCollection.clusterPlacemarks. Он принимает два аргумента:

    • clusterRadius — минимальное расстояние в единицах между объектами, которые остаются в отдельных кластерах.
    • minZoom — минимальный уровень масштабирования, отображающий кластеры.
    clusterizedCollection.clusterPlacemarks(60.0, 15)
    

    Важно

    ClusterizedPlacemarkCollection.clusterPlacemarks следует вызывать явно каждый раз, когда метки добавляются в кластеризованные коллекции или удаляются из них.

    Иначе кластеризованные метки не будут повторно отображаться.

    Кластеризованные метки с разным масштабом:

    Кластеры

Исходный код

Полные примеры кода из руководства смотрите в приложении map-objects в нашем GitHub репозитории.