Woosmap for Flutter - Show Indoor map

Get started with the Woosmap Indoor JS API. View simple examples, learn the concepts, and create custom indoor maps for your application.

  1. How to display a Indoor maps
  2. Accessing various functions in WoosmapMapViewWidget
  3. Fetching and displaying direction
  4. Indoor Navigation
  5. Supporting Indoor function
  6. Supporting IndoorWidget function

You can use the Woosmap Map-Js flutter plugin to embed interactive indoor maps directly into your Application.

How to display a Indoor maps

  1. Instantiating a WoosmapMapViewWidget.
lib/indoor_snippet.dart
        WoosmapMapViewWidget.create(
  wooskey: AppConstants.of(context)?.wooskey ?? "",
  widget: true,
  activate_indoor_product: true,
  indoorRendererConfiguration: IndoorRendererOptions(
    centerMap: true,
    defaultFloor: 3
  ),
  indoorWidgetConfiguration: IndoorWidgetOptions (
    units: UnitSystem.metric,
    ui: IndoorWidgetOptionsUI(
      primaryColor: "#318276",
      secondaryColor: "#004651"
    ),
  ),
  onRef: (p0) async {
    _controller = p0;
    reloadMenu();
  },
  indoor_venue_loaded: (message) {
    debugPrint(jsonEncode(message));
  },
  indoor_feature_selected: (message) {
    debugPrint(jsonEncode(message));
  },
  indoor_level_changed: (message) {
    debugPrint("$message");
  },
  indoor_user_location: (message) {
    debugPrint(jsonEncode(message));
  },
  indoor_directions: (message) {
    _controller?.setDirections(message);
    debugPrint(jsonEncode(message));
  },
  indoor_highlight_step: (message) {
    debugPrint(jsonEncode(message));
  },
);

    
        import 'package:flutter/widgets.dart';

class AppConstants extends InheritedWidget {
  static AppConstants? of(BuildContext context) =>
      context.dependOnInheritedWidgetOfExactType<AppConstants>();

  const AppConstants({required super.child, super.key});

  final String privateKeyiOS = "<<Your private iOS woosmap key>>";
  final String privateKeyAndroid = "<<Your private Android woosmap key>>";
  @override
  bool updateShouldNotify(AppConstants oldWidget) => false;
}

    
        import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:woosmap_flutter/woosmap_flutter.dart';
import './constants.dart';

class IndoorSnippet extends StatefulWidget {
  const IndoorSnippet({super.key});

  @override
  State<IndoorSnippet> createState() => _IndoorSnippetState();
}

class _IndoorSnippetState extends State<IndoorSnippet> {
  WoosmapController? _controller;
  @override
  void initState() {
    super.initState();
    if (_controller != null) {
      debugPrint("info ===> Indoor controller not initialize");
    }
  }

  Future<void> reloadMenu() async {
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Woosmap Indoor app'),
        actions: <Widget>[
          SampleMenu(webViewController: _controller, indoorVenue: "wgs_mtp"),
        ],
      ),
      body: SafeArea(
        child: Column(
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            Expanded(
                child: Align(
                    alignment: const AlignmentDirectional(-1, -1),
                    child: WoosmapMapViewWidget.create(
                      wooskey: Platform.isAndroid
                          ? AppConstants.of(context)?.privateKeyAndroid ?? ""
                          : AppConstants.of(context)?.privateKeyiOS ?? "",
                      widget: true,
                      activate_indoor_product: true,
                      default_indoor_venue_key: "wgs_mtp",
                      indoorRendererConfiguration: IndoorRendererOptions(
                          centerMap: true,
                          defaultFloor: 3,
                          snapToVenueBounds: true,
                          polylineOptions: IndoorPolylineOptions(
                              color: "#643843",
                              strokeColor: "#643843",
                              highlightColor: "#C88EA7")),
                      indoorWidgetConfiguration: IndoorWidgetOptions(
                        units: UnitSystem.metric,
                        ui: IndoorWidgetOptionsUI(
                          primaryColor: "#318276",
                          secondaryColor: "#004651",
                        ),
                      ),
                      onRef: (p0) async {
                        _controller = p0;
                        reloadMenu();
                      },
                      indoor_venue_loaded: (message) {
                        debugPrint(jsonEncode(message));
                        // ScaffoldMessenger.of(context).showSnackBar(
                        //   SnackBar(content: Text(jsonEncode(message))),
                        // );
                      },
                      indoor_feature_selected: (message) {
                        debugPrint(jsonEncode(message));
                      },
                      indoor_level_changed: (message) {
                        debugPrint("$message");
                      },
                      indoor_user_location: (message) {
                        debugPrint(jsonEncode(message));
                      },
                      indoor_directions: (message) {
                        _controller?.setDirections(message);
                        debugPrint(jsonEncode(message));
                      },
                      indoor_highlight_step: (message) {
                        debugPrint(jsonEncode(message));
                      },
                      indoor_navigation_started: () {
                        debugPrint("indoor_navigation_started");
                      },
                      indoor_navigation_exited: () {
                        debugPrint("indoor_navigation_exited");
                      },
                      dblclick: (location) {
                        _controller?.getLevel().then((level) {
                          _controller?.setUserLocation(
                              lat: location.lat,
                              lng: location.lng,
                              level: level,
                              bearing: 0,
                              forcefocus: false);
                        });
                      },
                    )))
          ],
        ),
      ),
    );
  }
}

enum MenuOptions {
  showVenue,
  showWorldMap,
  changeFloor,
  getFloor,
  showUserPosition,
  getUserPosition,
  showItinerary,
  checkUserInside,
  highlightFeatureByRef,
  highlightFeature,
  directions,
  directionsPoi,
  directionsRef,
  directionsWayPoint,
  directionsMode,
  startNavigation,
  exitNavigation,
  clearDirections,
  filterPois,
  clearFilterPois,
}

class SampleMenu extends StatelessWidget {
  const SampleMenu(
      {super.key, required this.webViewController, required this.indoorVenue});

  final WoosmapController? webViewController;
  final String indoorVenue;

  @override
  Widget build(BuildContext context) {
    return PopupMenuButton<MenuOptions>(
      key: const ValueKey<String>('ShowPopupMenu'),
      onSelected: (MenuOptions value) {
        switch (value) {
          case MenuOptions.showVenue:
            _onShowVenue();
            break;
          case MenuOptions.showUserPosition:
            _onShowUserPosition();
            break;
          case MenuOptions.changeFloor:
            _onChangeFloor();
            break;
          case MenuOptions.showWorldMap:
            _onShowWorldMap();
            break;
          case MenuOptions.highlightFeatureByRef:
            _onHighlightFeatureByRef();
            break;
          case MenuOptions.highlightFeature:
            _onHighlightFeature();
            break;
          case MenuOptions.directionsMode:
            _onDirectionsMode();
            break;
          case MenuOptions.directions:
            _onDirections();
            break;
          case MenuOptions.directionsPoi:
            _onDirectionsPoi();
            break;
          case MenuOptions.directionsRef:
            _onDirectionsRef();
            break;
          case MenuOptions.directionsWayPoint:
            _onDirectionsWayPoint();
            break;
          case MenuOptions.startNavigation:
            _startNavigation();
            break;
          case MenuOptions.exitNavigation:
            _exitNavigation();
            break;
          case MenuOptions.clearDirections:
            _onClearDirections();
            break;
          case MenuOptions.filterPois:
            _onFilterPOIs();
            break;
          case MenuOptions.clearFilterPois:
            _onClearFilterPOIs();
            break;
          case MenuOptions.getFloor:
            _onGetFloor().then((value) {
              if (value != null) {
                if (!context.mounted) return;
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text("You are on floor $value")),
                );
              }
            });
            break;
          case MenuOptions.getUserPosition:
            _onGetIndoorUserLocation().then((value) {
              if (value != null) {
                if (!context.mounted) return;
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(
                      content: Text(
                          "You are at ${value.position.lat},${value.position.lng} on floor ${value.level}")),
                );
              }
            });
            break;
          case MenuOptions.showItinerary:
            _onShowItinerary();
            break;
          case MenuOptions.checkUserInside:
            _onCheckUserInside().then((value) {
              if (value != null) {
                if (!context.mounted) return;
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(
                      content: Text(
                          "You are ${value == true ? "inside" : "outside"}")),
                );
              }
            });
            break;
        }
      },
      itemBuilder: (BuildContext context) => [
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.showWorldMap,
          child: Text('Show World Map'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.showVenue,
          child: Text('Show Indoor venue(MTP)'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.changeFloor,
          child: Text('Change floor to 3'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.getFloor,
          child: Text('Get Floor number'),
        ),
        const PopupMenuDivider(
          height: 20,
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.highlightFeatureByRef,
          child: Text('Highlight feature (Ref)'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.highlightFeature,
          child: Text('Highlight feature (id)'),
        ),
        const PopupMenuDivider(
          height: 20,
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.showUserPosition,
          child: Text('User Position'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.getUserPosition,
          child: Text('Get User Position'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.checkUserInside,
          child: Text('Check User inside'),
        ),
        const PopupMenuDivider(
          height: 20,
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.showItinerary,
          child: Text('Show Itinerary'),
        ),
        const PopupMenuDivider(
          height: 20,
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.directionsMode,
          child: Text('Directions Mode (wheelchair)'),
        ),
        const PopupMenuDivider(
          height: 20,
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.directions,
          child: Text('Directions(Lat/Lng)'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.directionsPoi,
          child: Text('Directions (Poi id)'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.directionsRef,
          child: Text('Directions (Poi Ref)'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.directionsWayPoint,
          child: Text('Directions (waypoint)'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.startNavigation,
          child: Text('Start Navigation'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.exitNavigation,
          child: Text('Exit Navigation'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.clearDirections,
          child: Text('Remove Path'),
        ),
        const PopupMenuDivider(
          height: 20,
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.filterPois,
          child: Text('Filter POIs'),
        ),
        const PopupMenuItem<MenuOptions>(
          value: MenuOptions.clearFilterPois,
          child: Text('Remove Filter on POIs'),
        ),
      ],
    );
  }

  Future<void>? _onShowVenue() {
    // Send a message with the user agent string to the Toaster JavaScript channel we registered
    // with the WebView.
    return webViewController?.setVenue(indoorVenue);
  }

  Future<void>? _onShowWorldMap() {
    // Send a message with the user agent string to the Toaster JavaScript channel we registered
    // with the WebView.
    return webViewController?.loadIndoorMap('');
  }

  Future<void>? _onChangeFloor() {
    // Send a message with the user agent string to the Toaster JavaScript channel we registered
    // with the WebView.
    return webViewController?.setFloor(3);
  }

  Future<void>? _onShowUserPosition() {
    return webViewController?.setUserLocation(
        lat: 43.606573820824764,
        lng: 3.92177514731884,
        level: 3,
        forcefocus: true);
  }

  Future<void>? _onHighlightFeatureByRef() {
    return webViewController?.highlightFeatureByRef(
        byref: 'tropiques',
        padding: WoosPadding(top: 300, bottom: 0, left: 0, right: 0));
  }

  Future<void>? _onHighlightFeature() {
    return webViewController?.highlightFeature(
        featureId: '34349', silent: false);
  }

  Future<void>? _onDirectionsMode() {
    return webViewController?.setDirectionsMode('wheelchair');
  }

  Future<void>? _onDirections() {
    webViewController
        ?.directions(DirectionParameter(
            venueId: indoorVenue,
            origin: LatLng(lat: 43.60664187325, lng: 3.921814671575),
            originLevel: 3,
            destination: LatLng(lat: 43.60665215333, lng: 3.921680093435),
            destinationLevel: 3,
            language: "en",
            units: UnitSystem.metric,
            mode: "wheelchair"))
        .then((route) => {
              if (route != null) {webViewController?.setDirections(route)}
            });
    return null;
  }

  Future<void>? _onDirectionsPoi() {
    webViewController
        ?.directions(DirectionParameter(
            venueId: indoorVenue,
            originId: 5071897,
            destinationId: 5071858,
            language: "en",
            units: UnitSystem.metric,
            mode: "wheelchair"))
        .then((route) => {
              if (route != null) {webViewController?.setDirections(route)}
            });
    return null;
  }

  Future<void>? _onDirectionsRef() {
    webViewController
        ?.directions(DirectionParameter(
            venueId: indoorVenue,
            originId: "ref:meeting001",
            destinationId: "ref:tropiques",
            language: "en",
            units: UnitSystem.metric,
            mode: "wheelchair"))
        .then((route) => {
              if (route != null) {webViewController?.setDirections(route)}
            });
    return null;
  }

  Future<void>? _onDirectionsWayPoint() {
    webViewController
        ?.directions(DirectionParameter(
            venueId: indoorVenue,
            origin: LatLng(lat: 43.60664187325, lng: 3.921814671575),
            originLevel: 3,
            destination: LatLng(lat: 43.60665215333, lng: 3.921680093435),
            destinationLevel: 3,
            language: "en",
            units: UnitSystem.metric,
            mode: "wheelchair",
            waypoints: ["ref:meeting001", "ref:tropiques"]))
        .then((route) => {
              if (route != null) {webViewController?.setDirections(route)}
            });
    return null;
  }

  Future<void>? _startNavigation() {
    return webViewController?.startNavigation();
  }

  Future<void>? _exitNavigation() {
    return webViewController?.exitNavigation();
  }

  Future<void>? _onClearDirections() {
    return webViewController?.clearDirections();
  }

  Future<void>? _onFilterPOIs() {
    return webViewController?.filterPois(advancedFilter: 'room:=meeting');
  }

  Future<void>? _onClearFilterPOIs() {
    return webViewController?.filterPois(advancedFilter: '');
  }

  Future<int?> _onGetFloor() async {
    int? result;
    result = await webViewController?.getLevel();
    return result;
  }

  Future<IndoorPosition?> _onGetIndoorUserLocation() async {
    try {
      IndoorPosition? currentPosition =
          await webViewController?.getUserLocation();
      return currentPosition;
    } catch (e) {
      return null;
    }
  }

  Future<bool?> _onCheckUserInside() async {
    bool? result;
    try {
      IndoorPosition? currentPosition =
          await webViewController?.getUserLocation();
      if (currentPosition == null) return null;

      result = await webViewController?.isUserInsideVenue(
          lat: currentPosition.position.lat, lng: currentPosition.position.lng);
    } catch (e) {
      return null;
    }

    return result;
  }

  Future<void>? _onShowItinerary() {
    // return webViewController?.showItinerary();

    return webViewController?.showItinerary(
        origin: null, destination: '9758902');
  }
}

    

Accessing various functions in WoosmapMapViewWidget

lib/indoor_snippet.dart
        _controller.setVenue('wgs_mtp');

    
lib/indoor_snippet.dart
        _controller.loadIndoorMap('');

    
lib/indoor_snippet.dart
        _controller.setFloor(3);

    
lib/indoor_snippet.dart
        _controller.setUserLocation(43.606573820824764, 3.92177514731884, 3, 0, true);

    
lib/indoor_snippet.dart
        _controller.highlightFeatureByRef('tropiques');

    
lib/indoor_snippet.dart
        _controller.setDirectionsMode('wheelchair');

    
lib/indoor_snippet.dart
        _controller.filterPois(advancedFilter: 'room:=meeting');

    

you can also pass an optional boolean parameter ignoreZoomRules. If true, ignores the zoom rules for the filtered POIs. Default value if false.

Fetching and displaying direction

Note: Class DirectionParameter is deprecated. We suggest you use new IndoorDirectionRequest instead.

lib/indoor_snippet.dart
        _controller.directions(IndoorDirectionRequest(
        venueId: 'wgs_mtp',
        origin: LatLng(lat: 43.60664187325, lng: 3.921814671575),
        originLevel: 3,
        destination: LatLng(lat: 43.60665215333, lng: 3.921680093435),
        destinationLevel: 3,
        language: "en",
        units: UnitSystem.metric,
        mode: "wheelchair",
    ))
    .then((route) => {_controller.setDirections(route)});

    
lib/indoor_snippet.dart
        _controller.directions(IndoorDirectionRequest(
        venueId: 'wgs_mtp',
        originId: 3694972,
        destinationId: 3694921,
        language: "en",
        units: UnitSystem.metric,
        mode: "wheelchair",
    ))
    .then((route) => {_controller?.setDirections(route)});

    
lib/indoor_snippet.dart
        _controller.directions(IndoorDirectionRequest(
        venueId: 'wgs_mtp',
        originId: "ref:meeting002",
        destinationId: "ref:tropiques",
        language: "en",
        units: UnitSystem.metric,
        mode: "wheelchair"
        ))
        .then((route) => {_controller.setDirections(route)});

    
lib/indoor_snippet.dart
        _controller.directions(IndoorDirectionRequest(
        venueId: 'wgs_mtp',
        originId: "ref:meeting002",
        destinationId: "ref:tropiques",
        waypoints: ["ref:meeting001", "ref:tropiques"]
        ))
        .then((route) => {_controller.setDirections(route)});

    

Indoor Navigation

To initiate navigation experience you need to call following methods of the WoosmapController object in the same order as given below.

  1. directions - As explained in the earlier section directions method will find the route between two points inside an indoor venue. This method returns a route object upon it’s completion.

  2. setDirections - This method will plot the given route on the map. You can pass the route object returned by directions method.

  3. startNavigation - This method will initiate the “Turn By Turn” navigation experience.

lib/indoor_snippet.dart
        _controller.startNavigation();

    
  1. exitNavigation - This method will result in the exit from “Turn By Turn” navigation mode.
lib/indoor_snippet.dart
        _controller.exitNavigation();

    
  1. clearDirections - Removes the plotted path on the map. If the navigation experience is started then it first exits from the navigation then removes the path.
lib/indoor_snippet.dart
        _controller.clearDirections(); 

    

Please note that setDirections method will no longer trigger navigation. Method startNavigation should explicitly be called to initiate the navigation.

Supporting Indoor function

lib/indoor_snippet.dart
        _controller.setUserLocation(
        lat: 43.606573820824764,
        lng: 3.92177514731884,
        level: 3,
        forcefocus: true);

    
lib/indoor_snippet.dart
        IndoorPosition currentPosition =
            await _controller.getUserLocation();

    
lib/indoor_snippet.dart
            bool? status;
    try {
    IndoorPosition? currentPosition =
        await _controller.getUserLocation();
    if (currentPosition == null) return null;

    status = await _controller.isUserInsideVenue(
        lat: currentPosition.position.lat, lng: currentPosition.position.lng);
    } catch (e) {
    return null;
    }

    
lib/indoor_snippet.dart
            result = await _controller.getLevel();

    
lib/indoor_snippet.dart
            _controller.setVenue(`test`);

    
lib/indoor_snippet.dart
        _controller?.setFloor(3);

    
lib/indoor_snippet.dart
        _controller?.highlightFeatureByRef(
    byref: 'tropiques',
    padding: WoosPadding(top: 300, bottom: 0, left: 0, right: 0));

    
lib/indoor_snippet.dart
        _controller.highlightFeature(
        featureId: '34349', silent: false);

    
lib/indoor_snippet.dart
            _controller.setDirectionsMode('wheelchair');

    
lib/indoor_snippet.dart
        _controller.filterPois(advancedFilter: 'room:=meeting');

    

Supporting IndoorWidget function

lib/indoor_snippet.dart
            _controller.showItinerary();

    
            _controller.showItinerary(
        origin: '9754000', destination: '9758902');

    
            _controller.showItinerary(
        origin: '43.606573820824764,3.92177514731884,3', destination: '9758902');

    
            _controller.showItinerary(
        origin: '<<User position>>', destination: '9758902');

    
Was this article helpful?
Have more questions? Submit a request