How to show multiple sets of polylines in Flutter on one Google map

4,649

Solution 1

You have to create a list of object which contains lat long. Add polylines coordinates and markers into the list. As showing in the link.

Solution 2

  1. Create a method that generates a polyline:

     Future<Polyline> _getRoutePolyline(
       {required LatLng start,
       required LatLng finish,
       required Color color,
       required String id,
       int width = 6}) async {
     // Generates every polyline between start and finish
     final polylinePoints = PolylinePoints();
     // Holds each polyline coordinate as Lat and Lng pairs
     final List<LatLng> polylineCoordinates = [];
    
     final startPoint = PointLatLng(start.latitude, start.longitude);
     final finishPoint = PointLatLng(finish.latitude, finish.longitude);
    
     final result = await polylinePoints.getRouteBetweenCoordinates(
       _googleApiKey,
       startPoint,
       finishPoint,
     );
     if (result.points.isNotEmpty) {
       // loop through all PointLatLng points and convert them
       // to a list of LatLng, required by the Polyline
       result.points.forEach((PointLatLng point) {
         polylineCoordinates.add(
           LatLng(point.latitude, point.longitude),
         );
       });
     }
     final polyline = Polyline(
       polylineId: PolylineId(id),
       color: color,
       points: polylineCoordinates,
       width: width,
     );
     return polyline;
     }
    
  2. Generate as many polylines a you want:

     Future<Set<Polyline>> _getTwoPolylines() async {
     // Use your location.
     const firstPolylineStart = LatLng(49.818453, 24.076606);
     const firstPolylineFinish = LatLng(49.834409, 24.067875);
    
     final firsPolyline = await _getRoutePolyline(
       start: firstPolylineStart,
       finish: firstPolylineFinish,
       color: Colors.green,
       id: 'firstPolyline',
     );
    
     // Use your location.
     const secondPolylineStart = LatLng(49.836510, 24.064096);
     const secondPolylineFinish = LatLng(49.840191, 24.043384);
    
     final secondPolyline = await _getRoutePolyline(
       start: secondPolylineStart,
       finish: secondPolylineFinish,
       color: Colors.red,
       id: 'secondPolyline',
     );
    
     final Set<Polyline> polylines = {};
     polylines.add(firsPolyline);
     polylines.add(secondPolyline);
    
     return polylines;
     }
    
  3. Set the generated polylines to GoogleMap (polylines field).

Share:
4,649
Daniel Mintz
Author by

Daniel Mintz

Updated on December 12, 2022

Comments

  • Daniel Mintz
    Daniel Mintz over 1 year

    I am trying to show multiple sets of different polylines (each set represents one cycling route with its own start and endpoint).

    There are ten routes in total I am bringing in from a JSON file. The problem is the map is consolidating all the individual ten routes into one mammoth polyline.

    So It is sort of connecting them all together (you can just make out the very straight line connecting between each route and only one startCap and endCap icon).

    I would expect/want to see ten different startCap and endCap icons and spaces between each polyline set.

    So how do I make the map show each polyline route as distinct routes?

    I am using flutter_polyline_points to decode the polyline route to the google map.

    Code below and the JSON is on the live link to make it easy to emulate if that helps.

    In essence in terms of steps :

    1. I create the google map and have one main central marker on it.

    2. I then bring in ten routes from a JSON file. These are ten objects in an array called Segments. Each object has a unique id I use for the PolyLineid and a unique polyline set of points in a string. So I bring in the JSON and then.

    3. iterate over each object and decode the polyline string to polyline coordinates which I attempt to then add to the map as multiple PolyLines.

    Also to here is the output I am seeing to bring the issue to life.

    enter image description here

    
    import 'package:flutter_polyline_points/flutter_polyline_points.dart';
    import 'package:http/http.dart' as http;
    import 'dart:convert';
    import 'dart:async';
    import 'package:flutter/material.dart';
    import 'package:google_maps_flutter/google_maps_flutter.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Multiple Polylines',
          theme: ThemeData(
            primarySwatch: Colors.orange,
          ),
          home: MapScreen(),
        );
      }
    }
    
    class MapScreen extends StatefulWidget {
      @override
      _MapScreenState createState() => _MapScreenState();
    }
    
    class _MapScreenState extends State<MapScreen> {
      GoogleMapController mapController;
      final Set<Marker> _marker = {};
      List<LatLng> polylineCoordinates = [];
      final Set<Polyline> _polylines = {};
      PolylinePoints polylinePoints = PolylinePoints();
      String lat = '51.200000';
      String long = '-0.440000';
      String title = 'Surrey Hills Mountain Biking';
      String location = 'Walking Bottom Car Park, Peaslake, Surrey';
    
      Future fetchStrava() async {
        final response = await http.get(
          'https://ibikeride.com/strava.json',
        );
        return parseStrava(response.body);
      }
    
      Future parseStrava(String responseBody) async {
        final Map<String, dynamic> parsed = await jsonDecode(responseBody);
        parsed['segments'].forEach((parse) {
          drawStrava(parse['points'], parse['id'].toString());
        });
      }
    
      Future drawStrava(points, polyid) async {
        var result = await polylinePoints.decodePolyline(points);
    
        if (result.isNotEmpty) {
          result.forEach((PointLatLng point) {
            polylineCoordinates.add(LatLng(point.latitude, point.longitude));
          });
        }
    
        _getPolyLine(polyid, polylineCoordinates);
      }
    
      void _getPolyLine(polyid, polyCord) {
        var id = PolylineId(polyid);
        _polylines.add(Polyline(
          polylineId: id,
          color: Colors.blue,
          width: 2,
          jointType: JointType.round,
          startCap: Cap.customCapFromBitmap(BitmapDescriptor.defaultMarker),
          endCap:
              Cap.customCapFromBitmap(BitmapDescriptor.defaultMarkerWithHue(90)),
          points: polyCord,
        ));
        setState(() {});
      }
    
      @override
      void initState() {
        super.initState();
        polylineCoordinates.clear();
        _marker.add(
          Marker(
              markerId: MarkerId('t'),
              infoWindow: InfoWindow(
                title: (title),
                snippet: (location),
              ),
              position: LatLng(double.parse(lat), double.parse(long)),
              icon: BitmapDescriptor.defaultMarker),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Container(
            child: GoogleMap(
              polylines: _polylines,
              mapType: MapType.hybrid,
              myLocationEnabled: true,
              initialCameraPosition: CameraPosition(
                target: LatLng(double.parse(lat), double.parse(long)),
                zoom: 13,
              ),
              markers: _marker,
              onMapCreated: (GoogleMapController controller) async {
                mapController = controller;
                await fetchStrava();
              },
            ),
          ),
        );
      }
    }
    

    The JSON file contents (live on the link in the code) https://ibikeride.com/strava.json is here for reference:

    {
        "segments": [
            {
                "id": 3592388,
                "name": "Barry Knows Best",
                "points": "uokwHvdtA@hAR`B^bBRnAQp@c@^w@b@o@t@Uv@c@r@c@hAsAxDOd@y@lDk@t@WVw@VeCl@u@\\@^k@jAKNi@b@iCVFBj@Cx@WpBKpA_@d@@Fn@W^c@RYBIHJ^"
            },
            {
                "id": 10925800,
                "name": "Combe Ln ",
                "points": "eauwHhezAHR@ZSlE?zDB|ALxAz@tGf@lCb@pA^|@j@l@XPvBf@bCL~BAdCMxA@Z?XDr@RTBT@h@?b@KLIPo@TuAJYPYz@u@~@aAn@]bAc@tCaA"
            },
            {
                "id": 22105173,
                "name": "Charlie & Mai's Rollercoast",
                "points": "wblwHfqvA_@@e@Es@Le@CI@]?YEE@CD@HT\\@H?HEHm@PWAKBW@G?KGIAOFWMQEQD_@@OCc@?MBEFYHI?KFGEE?ARVNFCj@B^?`@LR?HCJHX@NCXDg@TEEi@PS?WHGBEJOJE@GAOT[HG?K@KFCBKTBDSXg@F[ZECWZCP"
            },
            {
                "id": 2575161,
                "name": "Yoghurt Pots.",
                "points": "wljwHdoqASQKa@QIGSHOj@SHg@I[Ha@G[W[WiAa@Yc@UU_@k@UWE[Fg@Wc@OQQ_AC_AGa@He@Iy@Ii@AUSOAk@BSd@a@TS@MR"
            },
            {
                "id": 21544370,
                "name": "Shere to Gomshall",
                "points": "caswH`lxA?iCImCU{DM_DS_ICeKPiCJuCPwCZiAVe@X_@fBmBz@eA"
            },
            {
                "id": 14062811,
                "name": "Shere to Little London",
                "points": "ysrwHjxyAVVr@~AHL`@Xb@Hd@CVGd@G~Bg@z@YjAOl@Kl@Gt@O~@?f@G|@E~@MZIf@GtAWdA?b@N"
            },
            {
                "id": 20763954,
                "name": "All the Novas",
                "points": "uckwHvvwAc@Gk@MmB{@q@KSK[Yc@s@OS[SQEQCSUQIGIIOSiA[aAGKa@_@OKmA{A_Ai@w@q@[Qi@MgA?i@IUOg@Qe@IUOWUWMK?UFSBG?[Oq@Di@MYB]CK@MD[\\GDI?q@MKB"
            },
            {
                "id": 11514010,
                "name": "Captain Clunk (before the drops)",
                "points": "yqiwH|kwAMWGAg@NaA@}@VM@MCk@UOCs@@i@[ME_@EYFe@XQF_AJ"
            },
            {
                "id": 23855128,
                "name": "Abinger - Hammer to Sutton",
                "points": "{{qwH|hsA~@K`Bw@hA_@nAO`CCbAJ\\H~CbAjCxAh@RZFn@@rAKnAUhBk@j@KZ@ZJdAp@ND\\@NC\\KfAs@r@u@v@uARg@|@iDn@yAt@iA|AiBp@cAXq@lAcERa@VYZQt@Y|@UTQ`@w@t@qBPu@L{@\\wIH}@pBeM"
            },
            {
                "id": 13501471,
                "name": "Whitedown, turnoff till switchback",
                "points": "garwHbxoAsAaA_A]uA[yC_@UG_@Ys@u@kAy@eA{@mAq@k@e@eCkCiBuBu@w@e@m@_A_AaAqAgAqAu@Us@BcBViADeACqC]}A?k@F"
            }
        ]
    }
    

    I'm pretty new to coding but enjoying the journey.

    I have done a number of searches on here for the issue, Medium, and watched no end of youtube videos but still flummoxed. Any pointers appreciated.

    I sense it is something to do with creating a list of unique Polyines one adds to iteratively. Big Thanks

  • Daniel Mintz
    Daniel Mintz about 3 years
    Hi there and thanks for taking the time to read and give a pointer. I checked out your article on the link but struggled to understand and more to transpose that to my code and the problem I am facing. I'm still quite new to coding so probably my inexperience. I think something a bit more detailed in relation to my code here would really help. Thanks again.
  • Daniel Mintz
    Daniel Mintz about 3 years
    @Shira Actually, this has been brilliantly useful. I have managed to use JSON annotations to get the Json into a list using this guide here: link and then used your post as the guide to work out how to add the polyco=ordinates into the list and render. I will update with detail my post so others can see the specific steps I took but kudos and thanks.