magiclane_maps_flutter 3.1.1 copy "magiclane_maps_flutter: ^3.1.1" to clipboard
magiclane_maps_flutter: ^3.1.1 copied to clipboard

Magic Lane Maps SDK offers mapping, flexible routing, realtime traffic, voice navigation, POI search, custom styles, trip recording, map styles, alarms and more

example/lib/main.dart

// Example for the Magic Lane Maps SDK for Flutter.
// Showcases basic map usage, adding markers and performing a search.
//
// Over 60 examples are available on the Magic Lane developer website.
//
// Please see the Get Started with examples guide at
// https://developer.magiclane.com/docs/flutter/examples/get-started/

// ignore_for_file: avoid_print

import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart' hide Route;
import 'package:magiclane_maps_flutter/magiclane_maps_flutter.dart';

/// The API token is passed at build time using --dart-define.
const projectApiToken = String.fromEnvironment('GEM_TOKEN');

void main() {
  runApp(const GemMapExampleApp());
}

class GemMapExampleApp extends StatelessWidget {
  const GemMapExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'GemMap Example',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const GemMapExampleScreen(),
    );
  }
}

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

  @override
  State<GemMapExampleScreen> createState() => _GemMapExampleScreenState();
}

class _GemMapExampleScreenState extends State<GemMapExampleScreen> {
  // Keep a reference to the controller so the functions can use it.
  GemMapController? _mapController;

  /// Called when the GemMap is ready. Save the controller for later use.
  void _onMapCreated(final GemMapController controller) {
    setState(() {
      _mapController = controller;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          // The GemMap widget from the SDK. We attach a creation callback
          // to receive the [GemMapController].
          GemMap(
            onMapCreated: _onMapCreated,
            appAuthorization: projectApiToken,
          ),

          // Bottom-aligned horizontally scrollable list of buttons.
          if (_mapController != null)
            Positioned(
              left: 0,
              right: 0,
              bottom: 8,
              child: ActionButtonList(
                controller: _mapController!,
              ),
            ),
        ],
      ),
    );
  }
}

/// A simple horizontally scrollable list of action buttons
/// showcasing operations.
class ActionButtonList extends StatelessWidget {
  const ActionButtonList({
    super.key,
    required this.controller,
  });

  final GemMapController controller;

  /// Show points and lines markers on the map and center the camera to show all markers
  ///
  /// #### More examples of marker usage:
  /// - Add markers: https://developer.magiclane.com/docs/flutter/examples/maps-3dscene-examples/add-markers
  /// - Draw shapes: https://developer.magiclane.com/docs/flutter/examples/maps-3dscene-examples/draw-shapes
  ///
  /// #### Documentation regarding markers:
  /// - Marker structure: https://developer.magiclane.com/docs/flutter/guides/core/markers
  /// - Display markers on the map: https://developer.magiclane.com/docs/flutter/guides/maps/display-map-items/display-markers
  Future<void> _showMarkers() async {
    // The area where the camera will be centered, containing all markers.
    final area = RectangleGeographicArea(
      topLeft: Coordinates.fromLatLong(51.5310, -0.1524),
      bottomRight: Coordinates.fromLatLong(51.4889, -0.0474),
    );
    controller.centerOnArea(area);

    // =======================
    // POINT MARKERS
    // =======================

    // Create the point markers
    final Marker pointMarker1 = Marker()
      ..name = 'Point 1'
      ..setCoordinates(
        [
          Coordinates.fromLatLong(51.5262, -0.1097),
        ],
      );
    final Marker pointMarker2 = Marker()
      ..name = 'Point 2'
      ..setCoordinates(
        [
          Coordinates.fromLatLong(51.4931, -0.0966),
        ],
      );

    // Create a marker collection and add the point markers to it
    final MarkerCollection pointCollection =
        MarkerCollection(name: 'Point markers', markerType: MarkerType.point)
          ..add(pointMarker1)
          ..add(pointMarker2);

    // Create the render settings for the point markers
    // Applicable for all markers in the collection, use MarkerSketches for per-marker settings
    final MarkerCollectionRenderSettings pointMarkerSettings =
        MarkerCollectionRenderSettings(
      image: GemImage(
        imageId:
            GemIcon.waypointStart.id, // Can also set custom images as Uint8List
      ),
      labelTextSize: 3,
    );

    // Add the collection to the map
    controller.preferences.markers.add(
      pointCollection,
      settings: pointMarkerSettings,
    );

    // =======================
    // LINE MARKERS
    // =======================

    // Create the line marker (each marker is a separate line)
    final Marker lineMarker = Marker()
      ..name = 'Line 1'
      ..setCoordinates(
        [
          Coordinates.fromLatLong(51.4926, -0.1237),
          Coordinates.fromLatLong(51.5094, -0.1070),
          Coordinates.fromLatLong(51.5185, -0.0842),
          Coordinates.fromLatLong(51.5338, -0.0574),
        ],
      );

    final MarkerCollectionRenderSettings lineMarkerSettings =
        MarkerCollectionRenderSettings(
      polylineInnerColor: Colors.green,
      polylineInnerSize: 4.0,
    );

    final MarkerCollection lineCollectionRenderSettings = MarkerCollection(
      name: 'Line markers',
      markerType: MarkerType.polyline,
    )..add(lineMarker);

    controller.preferences.markers.add(
      lineCollectionRenderSettings,
      settings: lineMarkerSettings,
    );
  }

  /// Perform a simple text search for "Paris" and center to the first result
  ///
  /// #### More examples regarding search:
  /// - Text search: https://developer.magiclane.com/docs/flutter/examples/places-search/text-search
  /// - Address search: https://developer.magiclane.com/docs/flutter/examples/places-search/address-search
  /// - Search location: https://developer.magiclane.com/docs/flutter/examples/places-search/search-location
  /// - Search categories: https://developer.magiclane.com/docs/flutter/examples/places-search/search-category
  /// - What is nearby: https://developer.magiclane.com/docs/flutter/examples/places-search/what-is-nearby
  /// - What is nearby category: https://developer.magiclane.com/docs/flutter/examples/places-search/what-is-nearby-category
  /// - Search along route: https://developer.magiclane.com/docs/flutter/examples/places-search/search-along-route
  ///
  /// #### Documentation regarding search:
  /// - Search: https://developer.magiclane.com/docs/flutter/guides/category/search
  Future<void> _searchForParis() async {
    final Coordinates center = Coordinates.fromLatLong(49.20, 10.31);

    SearchService.search(
      'Paris',
      center,
      (final GemError err, final List<Landmark> results) async {
        if (results.isNotEmpty) {
          final Landmark first = results.first;
          controller.centerOnCoordinates(first.coordinates);
        } else {
          print('Paris search returned no results: $err');
        }
      },
    );
  }

  /// Search for food and drink places near the map center position and highlight and center to the first result
  ///
  /// #### More examples regarding search:
  /// - Text search: https://developer.magiclane.com/docs/flutter/examples/places-search/text-search
  /// - Address search: https://developer.magiclane.com/docs/flutter/examples/places-search/address-search
  /// - Search location: https://developer.magiclane.com/docs/flutter/examples/places-search/search-location
  /// - Search categories: https://developer.magiclane.com/docs/flutter/examples/places-search/search-category
  /// - What is nearby: https://developer.magiclane.com/docs/flutter/examples/places-search/what-is-nearby
  /// - What is nearby category: https://developer.magiclane.com/docs/flutter/examples/places-search/what-is-nearby-category
  /// - Search along route: https://developer.magiclane.com/docs/flutter/examples/places-search/search-along-route
  ///
  /// #### Documentation regarding search:
  /// - Search: https://developer.magiclane.com/docs/flutter/guides/category/search
  Future<void> _searchAndCenterFoodAndDrink() async {
    final GemMapController controller = this.controller;

    // Reset the cursor position to the center of the map
    await controller.resetMapSelection();

    // Get center coordinates of the current map view
    final Coordinates centerOfMapViewport = controller.cursorWgsPosition;

    // Get the food and drink landmark category
    final foodAndDrinkCategory = GenericCategories.getCategory(
      GenericCategoriesId.foodAndDrink.id,
    )!;

    // Set the preferences to search only for food and drink landmarks
    final SearchPreferences preferences = SearchPreferences(
      searchAddresses: false,
    );
    preferences.landmarks.addStoreCategoryId(
      foodAndDrinkCategory.landmarkStoreId,
      foodAndDrinkCategory.id,
    );

    // Perform the search around the center of the map view
    // using the provided preferences
    SearchService.searchAroundPosition(
      centerOfMapViewport,
      (err, results) async {
        if (results.isNotEmpty) {
          final Landmark selectedLandmark = results.first;

          // Highlight the found landmark
          controller.activateHighlight(
            [selectedLandmark],
          );

          // Center the map on the found landmark
          controller.centerOnCoordinates(
            selectedLandmark.coordinates,
            viewAngle: 0,
            animation: GemAnimation.linear(duration: Duration(seconds: 1)),
          );
        } else {
          print('No results found. Error: $err');
        }
      },
      preferences: preferences,
    );
  }

  /// Calculate a route between Amsterdam and Bruxelles, display it briefly and start a demo simulation
  ///
  /// ### More examples regarding routing and navigation:
  /// - Calculate route: https://developer.magiclane.com/docs/flutter/examples/routing-navigation/calculate-route
  /// - Route profile: https://developer.magiclane.com/docs/flutter/examples/routing-navigation/route-profile
  /// - Route instructions: https://developer.magiclane.com/docs/flutter/examples/routing-navigation/route-instructions
  /// - Truck Profile: https://developer.magiclane.com/docs/flutter/examples/routing-navigation/truck-profile
  /// - Calculate bike route: https://developer.magiclane.com/docs/flutter/examples/routing-navigation/calculate-bike-route
  /// - Public Transit: https://developer.magiclane.com/docs/flutter/examples/routing-navigation/public-transit
  /// - Navigate route: https://developer.magiclane.com/docs/flutter/examples/routing-navigation/navigate-route
  /// - Simulate route: https://developer.magiclane.com/docs/flutter/examples/routing-navigation/simulate-navigation
  /// - Lane instruction: https://developer.magiclane.com/docs/flutter/examples/routing-navigation/lane-instruction
  /// - etc.
  ///
  /// #### Documentation regarding routing and navigation:
  /// - Routes: https://developer.magiclane.com/docs/flutter/guides/core/routes
  /// - Navigation instructions: https://developer.magiclane.com/docs/flutter/guides/core/navigation-instructions
  /// - Routing: https://developer.magiclane.com/docs/flutter/guides/category/routing
  /// - Navigation: https://developer.magiclane.com/docs/flutter/guides/category/navigation
  Future<void> _routeAndNavigateAmsterdamToBruxelles() async {
    // Create landmarks for Amsterdam and Bruxelles
    // Can also be retrieved from a search result, map selection or other sources
    final Landmark amsterdam = Landmark.withLatLng(
      latitude: 52.3676,
      longitude: 4.9041,
    );
    final Landmark bruxelles = Landmark.withLatLng(
      latitude: 50.8503,
      longitude: 4.3517,
    );

    // Simple route preferences
    final RoutePreferences prefs = RoutePreferences(
      transportMode: RouteTransportMode.car, // Make a car route
      routeType: RouteType.fastest, // Prioritize fastest route
    );

    // Completer to wait for route calculation
    Completer<Route> routeCompleter = Completer<Route>();

    // Start route calculation (async operation, result provided via callback)
    RoutingService.calculateRoute(
      <Landmark>[amsterdam, bruxelles],
      prefs,
      (final GemError err, final List<Route> routes) async {
        if (err == GemError.success && routes.isNotEmpty) {
          final Route route = routes.first;
          routeCompleter.complete(route);
        } else {
          print('Route calculation failed: $err');
          routeCompleter.completeError(err);
        }
      },
    );

    // Wait for the route calculation to complete
    final route = await routeCompleter.future;

    // Compose a route label containing route information
    final timeDistanceInfo = route.getTimeDistance();
    final numberOfMinutes = (timeDistanceInfo.totalTimeS / 60).round();
    final numberOfKilometers = (timeDistanceInfo.totalDistanceM / 1000).round();
    final routeLabel =
        'AMS -> BRU\n$numberOfMinutes mins, $numberOfKilometers kms';

    // Add route to the map as main route
    controller.preferences.routes.add(route, true, label: routeLabel);

    // Calculate a viewport area box for the route to center the map
    // The RectType uses physical pixels for the screen dimensions
    final fullViewArea = controller.viewport;
    final routeArea = Rectangle<int>(
      50,
      300,
      fullViewArea.width - 100,
      fullViewArea.height - 700,
    );

    // Center the map on the route
    controller.centerOnRoute(route, screenRect: routeArea);

    // Keep route visible for a short moment
    await Future.delayed(const Duration(seconds: 3));

    // Start a simulation on the computed route
    // and listen to navigation events
    NavigationService.startSimulation(
      route,
      onNavigationInstruction: (instruction, events) {
        print('Next turn instruction: ${instruction.nextTurnInstruction}');

        // Also available on the NavigationInstruction object:
        // - next instruction image (abstract geometry image of the turn)
        // - lane image (image showing the correct lane for the turn)
        // - distance to next turn
        // - next speed limit variation
      },
      onNavigationStarted: () {
        print('Simulation started');
      },
      onDestinationReached: (final Landmark dest) {
        print('Destination reached: ${dest.description}');
      },
      onError: (final GemError error) {
        print('Navigation error: $error');
      },
      speedMultiplier: 2.0, // Speed up the simulation (2x real speed)
    );

    // Make the camera follow the simulated position
    controller.startFollowingPosition();
  }

  /// Clear all elements displayed on the map and cancel any ongoing navigation
  Future<void> _clearMap() async {
    await controller.preferences.markers.clear();
    controller.preferences.routes.clear();

    controller.deactivateHighlight();
    NavigationService.cancelNavigation();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: SizedBox(
        height: 40,
        child: Center(
          child: ListView(
            scrollDirection: Axis.horizontal,
            padding: const EdgeInsets.symmetric(horizontal: 12),
            children: [
              const SizedBox(width: 6),
              ElevatedButton(
                onPressed: () async {
                  await _clearMap();
                  await _showMarkers();
                },
                child: const Text('Show Markers'),
              ),
              const SizedBox(width: 12),
              ElevatedButton(
                onPressed: () async {
                  await _clearMap();
                  await _searchForParis();
                },
                child: const Text('Text Search'),
              ),
              const SizedBox(width: 12),
              ElevatedButton(
                onPressed: () async {
                  await _clearMap();
                  await _searchAndCenterFoodAndDrink();
                },
                child: const Text('Categories Search'),
              ),
              const SizedBox(width: 12),
              ElevatedButton(
                onPressed: () async {
                  await _clearMap();
                  await _routeAndNavigateAmsterdamToBruxelles();
                },
                child: const Text('Routing and Navigation'),
              ),
              const SizedBox(width: 12),
              ElevatedButton(
                onPressed: () async {
                  await _clearMap();
                },
                child: const Text('Reset'),
              ),
              const SizedBox(width: 6),
            ],
          ),
        ),
      ),
    );
  }
}
15
likes
150
points
229
downloads

Publisher

verified publishermagiclane.com

Weekly Downloads

Magic Lane Maps SDK offers mapping, flexible routing, realtime traffic, voice navigation, POI search, custom styles, trip recording, map styles, alarms and more

Homepage

Topics

#map #magic-lane #navigation #routing #location

Documentation

Documentation
API reference

License

unknown (license)

Dependencies

ffi, flutter, flutter_web_plugins, logging, meta, plugin_platform_interface

More

Packages that depend on magiclane_maps_flutter

Packages that implement magiclane_maps_flutter