Update polyline route with user's live location flutter

1,714

Solved the issue by clear the polylineCoordinates before adding the polyline.

Share:
1,714
Shriya Pandya
Author by

Shriya Pandya

Updated on December 27, 2022

Comments

  • Shriya Pandya
    Shriya Pandya over 1 year

    When i update the polyline code, on location change method, It gives me additional straight line. I want to update my polyline when user move from one source to destination. I am able to create a polyline route but i want that route become shorter with the location of the user. So i am replacing the source location with user's current location. And if user change takes different turn than the polyline should update as per it happens in google map apps.

    below is the code.

    import 'package:flutter_polyline_points/flutter_polyline_points.dart';
    import 'package:google_maps_flutter/google_maps_flutter.dart';
    import 'package:location/location.dart';
    import 'package:flutter/material.dart';
    import 'package:routelines/components/map_pin_pill.dart';
    import 'dart:async';
    import 'package:routelines/models/pin_pill_info.dart';
    
    const double CAMERA_ZOOM = 16;
    const double CAMERA_TILT = 80;
    const double CAMERA_BEARING = 30;
    
    const LatLng SOURCE_LOCATION = LatLng(22.993966, 72.498510);
    const LatLng DEST_LOCATION = LatLng(23.014672, 72.530558);
    
    class DirectionPage extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => DirectionPageState();
    }
    
    class DirectionPageState extends State<DirectionPage> {
      Completer<GoogleMapController> _controller = Completer();
      Set<Marker> _markers = Set<Marker>();
      Set<Polyline> _polylines = Set<Polyline>();
      List<LatLng> polylineCoordinates = [];
      PolylinePoints polylinePoints;
      String googleAPIKey = "<YourKey>";
      BitmapDescriptor sourceIcon;
      BitmapDescriptor destinationIcon;
      LocationData currentLocation;
      LocationData destinationLocation;
      Location location;
      double pinPillPosition = -100;
      int polyId = 1;
      PinInformation currentlySelectedPin = PinInformation(
          pinPath: '',
          avatarPath: '',
          location: LatLng(0, 0),
          locationName: '',
          labelColor: Colors.grey);
      PinInformation sourcePinInfo;
      PinInformation destinationPinInfo;
    
      @override
      void initState() {
        super.initState();
        location = new Location();
        setInitialLocation();
        polylinePoints = PolylinePoints();
        location.onLocationChanged().listen((LocationData cLoc) {
          currentLocation = cLoc;
          updatePinOnMap();
          setPolylines();
        });
        setSourceAndDestinationIcons();
      }
    
      @override
      void dispose() {
        super.dispose();
      }
    
      void setSourceAndDestinationIcons() async {
        BitmapDescriptor.fromAssetImage(
                ImageConfiguration(devicePixelRatio: 2.0), 'assets/driving_pin.png')
            .then((onValue) {
          sourceIcon = onValue;
        });
    
        BitmapDescriptor.fromAssetImage(ImageConfiguration(devicePixelRatio: 2.0),
                'assets/destination_map_marker.png')
            .then((onValue) {
          destinationIcon = onValue;
        });
      }
    
      void setInitialLocation() async {
        currentLocation = await location.getLocation();
        destinationLocation = LocationData.fromMap({
          "latitude": DEST_LOCATION.latitude,
          "longitude": DEST_LOCATION.longitude
        });
      }
    
      @override
      Widget build(BuildContext context) {
        CameraPosition initialCameraPosition = CameraPosition(
            zoom: CAMERA_ZOOM,
            tilt: CAMERA_TILT,
            bearing: CAMERA_BEARING,
            target: SOURCE_LOCATION);
        if (currentLocation != null) {
          initialCameraPosition = CameraPosition(
              target: LatLng(currentLocation.latitude, currentLocation.longitude),
              zoom: CAMERA_ZOOM,
              tilt: CAMERA_TILT,
              bearing: CAMERA_BEARING);
        }
        return Scaffold(
          body: Stack(
            children: <Widget>[
              GoogleMap(
                  myLocationEnabled: true,
                  compassEnabled: true,
                  tiltGesturesEnabled: false,
                  markers: _markers,
                  polylines: _polylines,
                  mapType: MapType.normal,
                  initialCameraPosition: initialCameraPosition,
                  onTap: (LatLng loc) {
                  },
                  onMapCreated: (GoogleMapController controller) {
                    controller.setMapStyle(Utils.mapStyles);
                    _controller.complete(controller);
                    print("map opened");
                    showPinsOnMap();
                  }),
              MapPinPillComponent(
                  pinPillPosition: pinPillPosition,
                  currentlySelectedPin: currentlySelectedPin)
            ],
          ),
        );
      }
    
      void showPinsOnMap() {
        if (currentLocation != null && destinationLocation != null) {
          var pinPosition =
              LatLng(currentLocation.latitude, currentLocation.longitude);
          // print("pinPosition >> $pinPosition");
          var destPosition =
              LatLng(destinationLocation.latitude, destinationLocation.longitude);
    
          sourcePinInfo = PinInformation(
              locationName: "Start Location",
              location: SOURCE_LOCATION,
              pinPath: "assets/driving_pin.png",
              avatarPath: "assets/square_pin.png",
              labelColor: Colors.blueAccent);
    
          destinationPinInfo = PinInformation(
              locationName: "End Location",
              location: DEST_LOCATION,
              pinPath: "assets/destination_map_marker.png",
              avatarPath: "assets/square_pin.png",
              labelColor: Colors.purple);
    
          _markers.add(Marker(
              markerId: MarkerId('sourcePin'),
              position: pinPosition,
              onTap: () {
                setState(() {
                  currentlySelectedPin = sourcePinInfo;
                  pinPillPosition = 0;
                });
              },
              icon: sourceIcon));
          // destination pin
          _markers.add(Marker(
              markerId: MarkerId('destPin'),
              position: destPosition,
              onTap: () {
                setState(() {
                  currentlySelectedPin = destinationPinInfo;
                  pinPillPosition = 0;
                });
              },
              icon: destinationIcon));
          setPolylines();
        }
      }
    
      void setPolylines() async {
        List<PointLatLng> result = await polylinePoints.getRouteBetweenCoordinates(
            googleAPIKey,
            currentLocation.latitude,
            currentLocation.longitude,
            destinationLocation.latitude,
            destinationLocation.longitude);
    
        if (result.isNotEmpty) {
          result.forEach((PointLatLng point) {
            polylineCoordinates.add(LatLng(point.latitude, point.longitude));
          });
          final String polylineIdVal = 'polyline_id_$polyId';
          polyId++;
          final PolylineId polylineId = PolylineId(polylineIdVal);
          _polylines = new Set<Polyline>();
          setState(() {
            _polylines.add( Polyline(
                width: 6,
                // set the width of the polylines
                polylineId: polylineId,
                geodesic: true,
                consumeTapEvents: true,
                color: Colors.blue,
                points: polylineCoordinates));
          });
        }
      }
    
      void updatePinOnMap() async {
        if (currentLocation != null && destinationLocation != null) {
          var pinPosition =
              LatLng(currentLocation.latitude, currentLocation.longitude);
          // print("pinPosition >> $pinPosition");
          var destPosition =
              LatLng(destinationLocation.latitude, destinationLocation.longitude);
    
          sourcePinInfo = PinInformation(
              locationName: "Start Location",
              location: SOURCE_LOCATION,
              pinPath: "assets/driving_pin.png",
              avatarPath: "assets/square_pin.png",
              labelColor: Colors.blueAccent);
    
          destinationPinInfo = PinInformation(
              locationName: "End Location",
              location: DEST_LOCATION,
              pinPath: "assets/destination_map_marker.png",
              avatarPath: "assets/square_pin.png",
              labelColor: Colors.purple);
    
          _markers.add(Marker(
              markerId: MarkerId('sourcePin'),
              position: pinPosition,
              onTap: () {
                setState(() {
                  currentlySelectedPin = sourcePinInfo;
                  pinPillPosition = 0;
                });
              },
              icon: sourceIcon));
          // destination pin
          _markers.add(Marker(
              markerId: MarkerId('destPin'),
              position: destPosition,
              onTap: () {
                setState(() {
                  currentlySelectedPin = destinationPinInfo;
                  pinPillPosition = 0;
                });
              },
              icon: destinationIcon));
    
          CameraPosition cPosition = CameraPosition(
            zoom: CAMERA_ZOOM,
            tilt: CAMERA_TILT,
            bearing: CAMERA_BEARING,
            target: LatLng(currentLocation.latitude, currentLocation.longitude),
          );
          final GoogleMapController controller = await _controller.future;
          controller.animateCamera(CameraUpdate.newCameraPosition(cPosition));
          setState(() {
            // print("pinPosition lat " + currentLocation.latitude.toString()+"  long "+ currentLocation.longitude.toString());
            var pinPosition =
                LatLng(currentLocation.latitude, currentLocation.longitude);
            sourcePinInfo.location = pinPosition;
            _markers.removeWhere((m) => m.markerId.value == 'sourcePin');
            _markers.add(Marker(
                markerId: MarkerId('sourcePin'),
                onTap: () {
                  setState(() {
                    currentlySelectedPin = sourcePinInfo;
                    pinPillPosition = 0;
                  });
                },
                position: pinPosition, // updated position
                icon: sourceIcon));
          });
        }
      }
    }
    

    enter image description here

    Any help would be appreciated!

    • Shashoug
      Shashoug over 2 years
      can you please provide me with PinInformation Class?
    • Shriya Pandya
      Shriya Pandya over 2 years
      This has been solved and accepted. @Shashoug
  • Umair
    Umair about 2 years
    If user current location changes as user move towards the destination and we move the marker. But how can we update the polyline? i want to show polyline from marker position to destination.