Panorama

With MapKit SDK, you can see what any terrain (for example, landmarks, roads or buildings) looks like in panoramic format.

Warning

The panorama functionality is available in the full version of the MapKit SDK.

Panorama types

MapKit SDK supports several types of panoramas:

  1. Street panoramas.

    street_panorama

  2. Interior panoramas.

    street_panorama

  3. Aerial panoramas.

    aerial_panorama

Viewing panorama

Follow these steps to view the panorama:

  1. Create and configure a panorama layer.

    PlacesFactory.instance.createPanoramaLayer(mapWindow)
      ..setStreetPanoramaVisible(true)
      ..setAirshipPanoramaVisible(true);
    
  2. Get the panorama ID depending on the selected panorama type:

  3. Finally, to open a panorama, its ID must be passed to PanoramaWidget.

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

    Also, in the documentation of the PanoramaPlayer class, you can find several methods that can be useful for setting up a panorama.

Panorama layer

The panorama layer allows you to see places on the map where you can open a panorama. After creating this layer, you should see new objects on the map that indicate places with a viewable panorama:

  • Blue dots and polylines indicate street or interior panoramas.
  • Balloon icons indicate aerial panoramas.

add_panorama_layer

Examples of getting the panorama ID

To get the ID of a street or interior panorama, you can use the following code:

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);

To get the aerial panorama ID, you can use the following code:

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);
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;
  }
}

Source code

You can check the example implementation of panorama viewing in the map_panorama application in our GitHub repository.