使用用户的实时位置颤振更新折线路线
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));
});
}
}
}
如有任何帮助,我们将不胜感激!
通过在添加折线之前清除折线坐标解决了这个问题。
当我更新折线代码时,在位置更改方法上,它给了我额外的直线。当用户从一个来源移动到目的地时,我想更新我的折线。我能够创建折线路线,但我希望该路线随着用户的位置而变短。所以我将源位置替换为用户的当前位置。如果用户更改的轮次不同,折线应根据 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));
});
}
}
}
如有任何帮助,我们将不胜感激!
通过在添加折线之前清除折线坐标解决了这个问题。