gebeta_gl 0.22.2 copy "gebeta_gl: ^0.22.2" to clipboard
gebeta_gl: ^0.22.2 copied to clipboard

A Flutter plugin for integrating MapLibre Maps inside a Flutter application on Android, iOS and web platforms.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show Uint8List, rootBundle;
import 'package:gebeta_gl/gebeta_gl.dart';
import 'dart:async';

// Location model to store pickup/dropoff points
class Location {
  final String name;
  final LatLng coordinates;

  Location(this.name, this.coordinates);
}

// Simulated location stream for demo purposes
class LocationStream {
  final _controller = StreamController<LatLng>.broadcast();
  Timer? _timer;
  bool _isTracking = false;
  LatLng _currentLocation;
  final List<LatLng> _routePoints;
  int _currentPointIndex = 0;

  LocationStream(this._currentLocation, this._routePoints);

  Stream<LatLng> get stream => _controller.stream;

  void startTracking() {
    if (_isTracking) return;
    _isTracking = true;
    
    _timer = Timer.periodic(Duration(seconds: 2), (timer) {
      if (_currentPointIndex < _routePoints.length) {
        _currentLocation = _routePoints[_currentPointIndex];
        _controller.add(_currentLocation);
        _currentPointIndex++;
      } else {
        stopTracking();
      }
    });
  }

  void stopTracking() {
    _isTracking = false;
    _timer?.cancel();
    _currentPointIndex = 0;
  }

  void dispose() {
    _timer?.cancel();
    _controller.close();
  }
}

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Gebeta Maps Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Gebeta maps Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // Your API key
  final String apiKey = 'your-api-key';
  
  // Store selected locations
  Location? pickupLocation;
  Location? dropoffLocation;
  GebetaMapController? mapController;
  String? styleString;
  LocationStream? locationStream;
  bool isTracking = false;
  LatLng? currentLocation;

  // Predefined locations (example points in Addis Ababa)
  final List<Location> availableLocations = [
    Location('Bole Airport', LatLng(8.9777, 38.7993)),
    Location('Meskel Square', LatLng(9.0327, 38.7617)),
    Location('Addis Ababa University', LatLng(9.0407, 38.7637)),
    Location('Ethiopian National Museum', LatLng(9.0327, 38.7617)),
    Location('Unity Park', LatLng(9.0327, 38.7617)),
  ];

  @override
  void initState() {
    super.initState();
    loadMapStyle().then((style) {
      setState(() {
        styleString = style;
      });
    });
  }
  
  @override
  void dispose() {
    locationStream?.dispose();
    super.dispose();
  }
  
  // Function to load the map style
  Future<String> loadMapStyle() async {
    return await rootBundle.loadString('assets/styles/basic.json');
  }

  Future<Uint8List> loadMarkerImage() async {
    var byteData = await rootBundle.load("assets/marker-black.png");
    return byteData.buffer.asUint8List();
  }

  Future<Uint8List> loadCurrentLocationMarkerImage() async {
    var byteData = await rootBundle.load("assets/marker-orange.png");
    return byteData.buffer.asUint8List();
  }
  
  void onMapCreated(GebetaMapController controller) async {
    // grab the controller on map created
    mapController = controller;
    // add marker image maybe
    var markerImage = await loadMarkerImage();
    var currentLocationMarkerImage = await loadCurrentLocationMarkerImage();
    controller.addImage('marker', markerImage);
    controller.addImage('current_location', currentLocationMarkerImage);
  }

  void updateLocations() {
    if (mapController == null) return;
    
    // Clear existing markers and lines
    mapController!.clearSymbols();
    mapController!.clearLines();

    // Add pickup marker if selected
    if (pickupLocation != null) {
      mapController!.addSymbol(
        SymbolOptions(
          iconSize: 2,
          iconImage: "marker",
          iconAnchor: "bottom",
          geometry: pickupLocation!.coordinates,
        ),
      );
    }

    // Add dropoff marker if selected
    if (dropoffLocation != null) {
      mapController!.addSymbol(
        SymbolOptions(
          iconSize: 2,
          iconImage: "marker",
          iconAnchor: "bottom",
          geometry: dropoffLocation!.coordinates,
        ),
      );
    }

    // Add current location marker if tracking
    if (currentLocation != null) {
      mapController!.addSymbol(
        SymbolOptions(
          iconSize: 2,
          iconImage: "current_location",
          iconAnchor: "bottom",
          geometry: currentLocation!,
        ),
      );
    }

    // Draw line between pickup and dropoff if both are selected
    if (pickupLocation != null && dropoffLocation != null) {
      mapController!.addLine(
        LineOptions(
          lineColor: '#FF0000',
          lineWidth: 2,
          geometry: [
            pickupLocation!.coordinates,
            dropoffLocation!.coordinates,
          ],
        ),
      );
    }
  }

  void startTracking() {
    if (pickupLocation == null || dropoffLocation == null) return;

    // Create a simulated route between pickup and dropoff
    final routePoints = [
      pickupLocation!.coordinates,
      LatLng(
        (pickupLocation!.coordinates.latitude + dropoffLocation!.coordinates.latitude) / 2,
        (pickupLocation!.coordinates.longitude + dropoffLocation!.coordinates.longitude) / 2,
      ),
      dropoffLocation!.coordinates,
    ];

    locationStream?.dispose();
    locationStream = LocationStream(pickupLocation!.coordinates, routePoints);
    
    locationStream!.stream.listen((location) {
      setState(() {
        currentLocation = location;
        updateLocations();
      });
    });

    locationStream!.startTracking();
    setState(() {
      isTracking = true;
    });
  }

  void stopTracking() {
    locationStream?.stopTracking();
    setState(() {
      isTracking = false;
      currentLocation = null;
      updateLocations();
    });
  }

  // Clear all markers and lines
  void clearMap() {
    if (mapController == null) return;
    
    stopTracking();
    mapController!.clearSymbols();
    mapController!.clearLines();
    setState(() {
      pickupLocation = null;
      dropoffLocation = null;
      currentLocation = null;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: styleString == null
          ? Center(child: CircularProgressIndicator())
          : Stack(
              children: [
                GebetaMap(
                  compassViewPosition: CompassViewPosition.topRight,
                  styleString: styleString!,
                  initialCameraPosition: CameraPosition(
                    target: LatLng(9.0192, 38.7525), // Addis Ababa
                    zoom: 10.0,
                  ),
                  onMapCreated: onMapCreated,
                  apiKey: apiKey,
                ),
                Positioned(
                  top: 16,
                  right: 16,
                  child: Row(
                    children: [
                      if (pickupLocation != null && dropoffLocation != null)
                        ElevatedButton.icon(
                          onPressed: isTracking ? stopTracking : startTracking,
                          icon: Icon(isTracking ? Icons.stop : Icons.play_arrow),
                          label: Text(isTracking ? 'Stop' : 'Start'),
                          style: ElevatedButton.styleFrom(
                            backgroundColor: isTracking ? Colors.red : Colors.green,
                            foregroundColor: Colors.white,
                            elevation: 2,
                          ),
                        ),
                      SizedBox(width: 8),
                      ElevatedButton.icon(
                        onPressed: clearMap,
                        icon: Icon(Icons.clear),
                        label: Text('Clear'),
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.white,
                          foregroundColor: Colors.black87,
                          elevation: 2,
                        ),
                      ),
                    ],
                  ),
                ),
                Positioned(
                  bottom: 16,
                  left: 16,
                  right: 16,
                  child: Container(
                    padding: EdgeInsets.all(16),
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(12),
                      boxShadow: [
                        BoxShadow(
                          color: Colors.black.withOpacity(0.1),
                          blurRadius: 8,
                          offset: Offset(0, 4),
                        ),
                      ],
                    ),
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: [
                        Text(
                          'Select Route',
                          style: TextStyle(
                            fontSize: 20,
                            fontWeight: FontWeight.bold,
                            color: Colors.black87,
                          ),
                        ),
                        SizedBox(height: 16),
                        Row(
                          children: [
                            Expanded(
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Text(
                                    'Pickup Location',
                                    style: TextStyle(
                                      fontSize: 14,
                                      color: Colors.black54,
                                    ),
                                  ),
                                  SizedBox(height: 8),
                                  Container(
                                    decoration: BoxDecoration(
                                      border: Border.all(color: Colors.grey.shade300),
                                      borderRadius: BorderRadius.circular(8),
                                    ),
                                    child: DropdownButtonHideUnderline(
                                      child: DropdownButton<Location>(
                                        value: pickupLocation,
                                        hint: Text('Select pickup'),
                                        isExpanded: true,
                                        padding: EdgeInsets.symmetric(horizontal: 12),
                                        items: availableLocations.map((Location location) {
                                          return DropdownMenuItem<Location>(
                                            value: location,
                                            child: Text(location.name),
                                          );
                                        }).toList(),
                                        onChanged: (Location? newValue) {
                                          setState(() {
                                            pickupLocation = newValue;
                                            updateLocations();
                                          });
                                        },
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                            SizedBox(width: 16),
                            Expanded(
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Text(
                                    'Dropoff Location',
                                    style: TextStyle(
                                      fontSize: 14,
                                      color: Colors.black54,
                                    ),
                                  ),
                                  SizedBox(height: 8),
                                  Container(
                                    decoration: BoxDecoration(
                                      border: Border.all(color: Colors.grey.shade300),
                                      borderRadius: BorderRadius.circular(8),
                                    ),
                                    child: DropdownButtonHideUnderline(
                                      child: DropdownButton<Location>(
                                        value: dropoffLocation,
                                        hint: Text('Select dropoff'),
                                        isExpanded: true,
                                        padding: EdgeInsets.symmetric(horizontal: 12),
                                        items: availableLocations.map((Location location) {
                                          return DropdownMenuItem<Location>(
                                            value: location,
                                            child: Text(location.name),
                                          );
                                        }).toList(),
                                        onChanged: (Location? newValue) {
                                          setState(() {
                                            dropoffLocation = newValue;
                                            updateLocations();
                                          });
                                        },
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
    );
  }
}
2
likes
150
points
319
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for integrating MapLibre Maps inside a Flutter application on Android, iOS and web platforms.

Repository (GitHub)
View/report issues

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

flutter, gebeta_gl_platform_interface

More

Packages that depend on gebeta_gl