使用用户的实时位置颤振更新折线路线

Update polyline route with user's live location flutter

当我更新折线代码时,在位置更改方法上,它给了我额外的直线。当用户从一个来源移动到目的地时,我想更新我的折线。我能够创建折线路线,但我希望该路线随着用户的位置而变短。所以我将源位置替换为用户的当前位置。如果用户更改的轮次不同,折线应根据 google 地图应用程序中发生的情况进行更新。

下面是代码。

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

如有任何帮助,我们将不胜感激!

通过在添加折线之前清除折线坐标解决了这个问题。