我在我的应用程序中使用 flutter_map,我在 flutter_map 中使用以下标题层显示了地图
TileLayer(
urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
//change base_snow_map to pistes
subdomains: ['a', 'b', 'c'],
tileProvider: CachedTileProvider(),
),
然后我使用资产文件夹中的 geoJson 文件中的数据在该地图上显示了雪地摩托路线。它包含显示雪地摩托路径的经纬度。我使用折线层来显示 snowMobile 路线
PolylineLayer(
polylineCulling: false,
polylines: myGeoJson.polylines,
),
现在我想,每当我点击 snowMobile 路线/折线上的两个点时,应该沿着 snowMobile 折线绘制一条路线,但我面临的问题是它直接连接这些点而不遵循 snowMobile 层的路径。以下是代码
class MapScreen extends StatefulWidget {
const MapScreen({Key? key}) : super(key: key);
@override
State<MapScreen> createState() => _MapScreenState();
}
class _MapScreenState extends State<MapScreen> {
@override
void initState() {
// TODO: implement initState
super.initState();
cacheTiles();
}
GeoJsonParser myGeoJson = GeoJsonParser();
var geoJSON;
GeoJsonFeatureCollection featureCollection = GeoJsonFeatureCollection();
cacheTiles() async {
try {
// initiate parser
geoJSON = await rootBundle.loadString('assets/export.geojson');
geoJSON = await convertIntToDouble(geoJSON);
featureCollection = await featuresFromGeoJson(geoJSON);
myGeoJson.parseGeoJsonAsString(geoJSON);
setState(() {
print("SHOW NOW");
});
} catch (e) {
print(e.toString());
setState(() {
print("Error NOW");
});
}
}
convertIntToDouble(geoJSON) async {
var data = await json.decode(geoJSON);
// Iterate over each feature
for (var feature in data['features']) {
// Iterate over each coordinate
for (var coordinate in feature['geometry']['coordinates']) {
// If the latitude or longitude value is an int, convert it to a double
if (coordinate is List && coordinate.length == 2) {
if (coordinate[0] is int) {
coordinate[0] = coordinate[0].toDouble();
}
if (coordinate[1] is int) {
coordinate[1] = coordinate[1].toDouble();
}
}
}
}
// Convert the modified data back to a geoJSON string
return json.encode(data);
}
MapController mapController = MapController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Flutter Map Example')),
body: FlutterMap(
options: MapOptions(
center: LatLng(63.1817371, 21.7348336),
zoom: 11,
onTap: (tapPosition, latLng) {
print(latLng);
_handleTap(latLng);
}),
mapController: mapController,
children: [
TileLayer(
urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
//change base_snow_map to pistes
subdomains: ['a', 'b', 'c'],
tileProvider: CachedTileProvider(),
),
PolylineLayer(
polylineCulling: false,
polylines: myGeoJson.polylines,
),
MarkerLayer(
markers: _tapPoints
.map(
(latLng) => Marker(
point: latLng,
width: 50,
height: 50,
builder: (context) => InkWell(
onTap: () {
setState(() {
_tapPoints.remove(latLng);
drawPolyLinesBetweenTappedPoints();
});
},
child: const Icon(
Icons.location_pin,
color: Colors.red,
size: 50,
),
),
),
)
.toList(),
),
],
),
);
}
List<LatLng> _tapPoints = [];
List<Polyline> polylines = [];
void _handleTap(LatLng latLng) async {
isThisTapExistInSnowMobile(latLng);
bool markerExists = _tapPoints.any((marker) => marker == latLng);
markerExists ? _tapPoints.remove(latLng) : _tapPoints.add(latLng);
if (_tapPoints.length >= 2) {
drawPolyLinesBetweenTappedPoints();
}
setState(() {});
}
drawPolyLinesBetweenTappedPoints() {
final geoJson = json.decode(geoJSON);
final List<LatLng> lineStringCoords = [];
geoJson['features'][0]['geometry']['coordinates'].forEach((coord) {
lineStringCoords.add(LatLng(coord[1], coord[0]));
});
print(lineStringCoords.length);
List<double> distances = [];
lineStringCoords.forEach((point) {
double distance1 = Distance().as(LengthUnit.Meter, point, _tapPoints[0]);
double distance2 = Distance().as(LengthUnit.Meter, point, _tapPoints[1]);
distances.add(distance1 + distance2);
});
// Find the two points in lineStringCoords that are closest to the start and end points in _tapPoints
int closest1 = distances.indexOf(distances.reduce(min));
int closest2 = distances.lastIndexOf(distances.reduce(min));
// Create a new list of LatLng objects that includes the start and end points in _tapPoints and the two closest points in lineStringCoords
List<LatLng> polylinePoints = [
_tapPoints[0],
lineStringCoords[closest1],
lineStringCoords[closest2],
_tapPoints[1]
];
// Sort the new list of LatLng objects by their distance from the start point in _tapPoints
polylinePoints.sort((a, b) => Distance()
.as(LengthUnit.Meter, _tapPoints[0], a)
.compareTo(Distance().as(LengthUnit.Meter, _tapPoints[0], b)));
final connectingLine = Polyline(
points: polylinePoints,
strokeWidth: 5.0,
color: Colors.black,
);
polylines.clear();
polylines.add(connectingLine);
setState(() {});
}
isThisTapExistInSnowMobile(LatLng latLng) {
print("aya");
myGeoJson.polylines.map((e) => e.points.map((data) {
print(data);
}));
}
LatLng findNearestPoint(List<LatLng> coordsList, LatLng targetPoint) {
double minDistance = double.infinity;
LatLng nearestPoint = coordsList.first;
for (final coord in coordsList) {
final distance = Distance().as(LengthUnit.Meter, targetPoint, coord);
if (distance < minDistance) {
minDistance = distance;
nearestPoint = coord;
}
}
return nearestPoint;
}
}