Панорама

MapKit SDK позволяет посмотреть, как выглядит какая-либо местность (например, достопримечательности, дороги или здания) в формате панорам.

Важно

Функционал панорам доступен в full-версии MapKit SDK.

Виды панорам

MapKit SDK поддерживает несколько видов панорам:

  1. Уличные панорамы.

    street_panorama

  2. Интерьерные панорамы.

    street_panorama

  3. Воздушные панорамы.

    aerial_panorama

Просмотр панорамы

Выполните следующие шаги, чтобы посмотреть панораму:

  1. Создайте и настройте слой панорам.

    PlacesFactory.instance.createPanoramaLayer(mapWindow)
      ..setStreetPanoramaVisible(true)
      ..setAirshipPanoramaVisible(true);
    
  2. Получите идентификатор панорамы в зависимости от выбранного типа панорамы:

    • Для получения идентификатора уличной или интерьерной панорамы используется метод PanoramaService.findNearest. В него нужно передать точку на карте для поиска ближайшей к ней панорамы.
    • Для получения идентификатора воздушной панорамы нужно при помощи GeoObject.metadataContainer получить объект AirshipTapInfo, в котором содержится panoramaId.
  3. Наконец, для открытия панорамы ее идентификатор нужно передать в PanoramaWidget.

    void navigateToPanorama(String panoramaId) {
      Navigator.of(context).push(
        PageRouteBuilder(
          pageBuilder: (context, animation, secondaryAnimation) {
            return PanoramaWidget(
              onPanoramaCreated: (PanoramaPlayer panoramaPlayer) {
                panoramaPlayer.openPanorama(panoramaId);
              },
            );
          },
        )
      );
    }
    

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

Слой панорам

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

  • Синие точки и полилинии обозначают уличные или интерьерные панорамы.
  • Иконки аэростата обозначают воздушные панорамы.

panorama_layer

Примеры получения идентификатора панорамы

Для получения идентификатора уличной или интерьерной панорамы вы можете использовать следующий код:

final class MapInputListenerImpl implements MapInputListener {

  final PanoramaService panoramaService;
  final PanoramaServiceSearchListener panoramaSearchListener;

  PanoramaServiceSearchSession? searchSession;

  const MapInputListenerImpl(
    this.panoramaService,
    this.panoramaSearchListener,
  );

  @override
  void onMapTap(Map map, Point point) {
    // You need to store reference to search session until panoramaSearchListener is notified
    searchSession = panoramaService.findNearest(
      point,
      panoramaSearchListener,
    );
  }

  @override
  void onMapLongTap(Map map, Point point) {}
}

final panoramaService = PlacesFactory.instance.createPanoramaService();

final panoramaSearchListener = PanoramaServiceSearchListener(
  onPanoramaSearchResult: (String panoramaId) => navigateToPanorama(panoramaId),
  onPanoramaSearchError: (error) {
    // Handle search error
  }
);

final mapInputListener = MapInputListenerImpl(
  panoramaService,
  panoramaSearchListener,
);

mapWindow.map.addInputListener(mapInputListener);
  • В коллбэке onMapTap(Map, Point) возвращается точка на карте, в которой произошло касание.
  • Далее эта точка передается в PanoramaService.findNearest для поиска идентификатора ближайшей к ней панорамы.
  • Когда идентификатор панорамы будет найден, он будет передан в PanoramaServiceSearchListener.
  • Подробнее про обработку тапов по карте можно почитать здесь.

Для получения идентификатора воздушной панорамы вы можете использовать следующий код:

final class LayersGeoObjectTapListenerImpl implements LayersGeoObjectTapListener {

  final bool Function(GeoObjectTapEvent) onObjectTapped;

  const LayersGeoObjectTapListenerImpl({
    required this.onObjectTapped,
  });

  @override
  bool onObjectTap(GeoObjectTapEvent event) => onObjectTapped(event);
}

final geoObjectTapListener = LayersGeoObjectTapListenerImpl(
  onObjectTapped: (event) {
    final geoObject = event.geoObject;
    final airshipTapInto = geoObject.airshipTapInfo;
    final point = geoObject.point;

    if (airshipTapInto != null && point != null) {
      navigateToPanorama(airshipTapInto.panoramaId);
      return true;
    }
    return false;
  }
);

mapWindow.map.addTapListener(geoObjectTapListener);
  • Важно заметить, что иконка аэростата, которой обозначается воздушная панорама на карте, является объектом класса GeoObject.
  • Поэтому для получения объекта GeoObject при нажатии на иконку воздушной панорамы нужно использовать класс LayersGeoObjectTapListener.
  • Далее при помощи GeoObject.metadataContainer вы сможете получить объект AirshipTapInfo, в котором содержится panoramaId.
  • Подробнее о том, как взаимодействовать с объектами GeoObject можно прочитать здесь.
extension GeoObjectAirshipTapInfo on GeoObject {
  AirshipTapInfo? get airshipTapInfo {
    return metadataContainer.get(AirshipTapInfo.factory);
  }
}

extension ToponymGeoObjectMetadata on GeoObject {
  SearchToponymObjectMetadata? get toponymMetadata {
    return metadataContainer.get(SearchToponymObjectMetadata.factory);
  }
}

extension PointFromGeometry on GeoObject {
  Point? get pointFromGeometry {
    return geometry.map((item) => item.asPoint())
        .whereType<Point>()
        .firstOrNull;
  }
}

extension GeoObjectPoint on GeoObject {
  Point? get point {
    return toponymMetadata?.balloonPoint ?? pointFromGeometry;
  }
}

Исходный код

Пример реализации просмотра панорам вы можете найти в приложении map_panorama в нашем репозитории на GitHub.

Предыдущая
Следующая