flutter_map 在现有的 PolylineLayer 上绘制路线(由 geoJson 数据绘制)

问题描述 投票:0回答:0

我在我的应用程序中使用 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;
  }
}
flutter polyline fluttermap
© www.soinside.com 2019 - 2024. All rights reserved.