Слой навигации

YMKNavigationLayer в NaviKit SDK представляет собой дополнительный слой на карте, который включает в себя пользовательский интерфейс (маршруты, точки маршрута, метка пользователя и баллуны) и логику их отображения. Кроме того, YMKNavigationLayer предоставляет API камеры, которое позволяет изменять положение карты на основе различных навигационных сценариев, например: слежение за меткой пользователя, обзор всего маршрута и свободный режим.

Создание

Используйте метод YMKNavigationLayerFactory.createNavigationLayer(with:roadEventsLayer:styleProvider:navigation:) для создания нового экземпляра навигационного слоя.

let navigationLayer = YMKNavigationLayerFactory.createNavigationLayer(
    with: mapWindow,
    roadEventsLayer: roadEventsLayer,
    styleProvider: navigationStyleProvider,
    navigation: navigation
)

Процесс создания roadEventsLayer был рассмотрен тут, создание navigation - тут.

После создания YMKNavigationLayer при включенном отслеживании локации у YMKNavigation, на карте отобразиться метка с текущим местоположением пользователя.

YMKNavigationStyleProvider

Отображение UI-элементов на навигационном слое карты определяется при помощи интерфейса YMKNavigationStyleProvider.

С помощью реализации YMKNavigationStyleProvider можно настроить стили отображения отдельных UI-элементов с помощью реализации нужного провайдера стилей:

Класс AutomotiveNavigationStyleProvider - это готовая реализация итерфейса YMKNavigationStyleProvider, которая содержит UI-элементы в фирменном стиле Яндекс Карт. Она поставляется в виде отдельной зависимости.

Для того, чтобы изменить некоторые стили UI-элементов, можно реализовать новый YMKNavigationStyleProvider, используя AutomotiveNavigationStyleProvider в качестве делегата:

class NavigationStyleProviderImpl: NSObject, YMKNavigationStyleProvider {

    private let defaultNavigationStyleProvider = AutomotiveNavigationStyleProvider()

    // Default style provider implementation
    override func balloonImageProvider() = styleProvider.balloonImageProvider()
    override func requestPointStyleProvider() = styleProvider.requestPointStyleProvider()
    override func userPlacemarkStyleProvider() = styleProvider.userPlacemarkStyleProvider()
    override func routePinsStyleProvider() = styleProvider.routePinsStyleProvider()

    func routeViewStyleProvider() -> YMKNavigationRouteViewStyleProvider {
        routeViewStyleProviderImpl
    }

    func balloonImageProvider() -> YMKNavigationBalloonImageProvider {
        defaultNavigationStyleProvider.balloonImageProvider()
    }

    func requestPointStyleProvider() -> YMKNavigationRequestPointStyleProvider {
        defaultNavigationStyleProvider.requestPointStyleProvider()
    }

    func userPlacemarkStyleProvider() -> YMKNavigationUserPlacemarkStyleProvider {
        defaultNavigationStyleProvider.userPlacemarkStyleProvider()
    }

    func routePinsStyleProvider() -> YMKNavigationRoutePinsStyleProvider {
        defaultNavigationStyleProvider.routePinsStyleProvider()
    }

    private var routeViewStyleProviderImpl: RouteViewStyleProviderImpl!

    private class RouteViewStyleProviderImpl: YMKNavigationRouteViewStyleProvider {

        init(defaultNavigationStyleProvider: YMKNavigationStyleProvider) {
            routeViewStyleProvider = defaultNavigationStyleProvider.routeViewStyleProvider()
        }

        private let routeViewStyleProvider: YMKNavigationRouteViewStyleProvider

        func provideRouteStyle(
            with flags: YMKDrivingFlags,
            isSelected: Bool,
            isNightMode: Bool,
            routeStyle: YMKNavigationRouteStyle
        ) {
            routeViewStyleProvider
                .provideRouteStyle(
                    with: flags,
                    isSelected: isSelected,
                    isNightMode: isNightMode,
                    routeStyle: routeStyle
                )
        }

        // Implementations of other methods through routeViewStyleProvider ...
    }
}

Таким образом, можно реализовать отдельный провайдер стилей для линии маршрута YMKNavigationRouteViewStyleProvider и изменить стиль отображения пробок на маршрутах. Для остальных UI-элементов используется стандартная реализация с помощью делегата AutomotiveNavigationStyleProvider.

Стили из YMKNavigationStyleProvider обновляются на каждый вызов YMKNavigationLayer.refreshStyle().

Подробнее с примером реализации YMKNavigationStyleProvider можно ознакомиться в демо-приложении.

Маршруты

Слой навигации отвечает за отображение маршрутов, которые хранятся в YMKNavigation.

Отображение маршрутов

Слой навигации способен отображать маршруты на карте. Отрисовка маршрутов происходит по следующему сценарию:

  1. При создании YMKNavigationLayer в него передается объект YMKNavigation, с помощью которого слой подписывается на состояние навигации и отслеживает изменение маршрутов в нем. Например, после запроса маршрутов с помощью обработчика событий YMKNavigationListener.onRoutesRequested(with:) навигация сообщает, что маршрут был запрошен и слой переводит камеру в режим обзора маршрутов.
  2. Затем навигация сообщает об успешном получении маршрутов, происходит вызов метода YMKNavigationListener.onRoutesBuilt() и слой отображает маршруты на карте по обновленным данным.

Таким образом, слой навигации отлеживает состояние маршрутов внутри YMKNavigation, отображает их на карте и при необходимости перерисовывает.

Мгновенное ведение

Чтобы пропустить этап сравнения альтернативных маршрутов в режиме обзора маршрутов и начать ведение по первому найденному маршруту следует начинать ведение сразу же после получения результатов запроса маршрутов в методе обработчике события YMKNavigationListener.onRoutesBuilt().

При этом, в момент когда маршруты уже были запрошена, но ведение еще не началось, можно заметить "промаргивание" UI-маршрутов. Чтобы этого избежать нужно скрыть UI навигационного слоя до начала ведения по маршруту. Например, используя метод YMKNavigationLayer.isVisible, или спрятать линии маршрута используя переопределение стилей через NavigationStyleProvider.

Источники маршрутов

NavigationLayer.getRoutesSources определяет какой именно тип маршрутов в данный момент отображает слой навигации:

  • navigation - результат запроса маршрутов через YMKNavigation при отображении маршрутов в режиме обзора.
  • guidance - текущий маршрут во время ведения при отображении маршрутов во время ведения.

Текущий маршрут

YMKNavigationLayer хранит информацию о текущем выбранном маршруте. При помощи вызова YMKNavigationLayer.selectRoute(withRoute:) можно изменить текущий выбранный маршрут в режиме обзора.

Пример назначения текущего маршрута:

class RouteViewListener: NSObject, YMKRouteViewListener {
    func onRouteViewTap(withRoute: YMKRouteView) {
        switch navigationLayer.routesSource {
        case .navigation:
            navigationLayer.selectRoute(withRoute: routeView)
        case .guidance:
            navigationLayer.navigation.switchToRoute(with: routeView.route)
        }
    }

    func onRouteViewsChanged() {
        guard navigationLayer.selectedRoute() == nil,
              let route = navigationLayer.routes.first else {
            return
        }
        navigationLayer.selectRoute(withRoute: route)
    }
}

let routeViewListener = RouteViewListener()
navigationLayer.addRouteViewListener(with: routeViewListener)

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

Примечание

По умолчанию после запроса маршрутов через YMKNavigation текущий маршрут в навигационном слое отсутствует, поэтому его нужно назначить вручную, например, с помощью YMKRouteViewListener.onRouteViewsChanged().

Точки маршрута

Слой навигации отвечает за отображение from, to и via точек во время ведения и обзора маршрута.

Для подписки на изменение точек и их нажатия используется интерфейс YMKRequestPointListener.

Пользовательская метка

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

Баллуны

Баллуны представляют собой UI-элементы на карте с надписью. Существует несколько видов баллунов:

  • баллун маневра во время ведения указывает на положение следующего маневра на маршруте;
  • баллун альтернативы показывает информацию о маршруте во время обзора, содержит информацию о сравнении текущего и выбранного маршрута.

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

Камера

Управление камерой происходит с помощью объета YMKCamera, который можно получить используя вызов YMKNavigationLayer.camera.

Переключение режимов камеры происходит с помощью метода YMKCamera.setCameraModeWith(_:animation:). Поддерживаются следующие типы режимов:

  • Following - режим слежения камеры за меткой пользователя во время ведения.
  • Overview - обзор запрошенных маршрутов.
  • Free - режим по умолчанию.

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

При помощи методов YMKCamera и YMKNavigationLayer можно изменять следующие параметры камеры:

  • автоматическое приближение камеры;
  • автоматический поворот камеры;
  • автоматическое переключение режимов камеры;
  • параметр корректировки приближения во время ведения;
  • включение/отключение 2D режима камеры.

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

Поддержаны следующие настройки видимой области карты:

Следующая