Daniel Mintz
Daniel Mintz

Reputation: 53

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

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

Upvotes: 2

Views: 8705

Answers (2)

IvanPavliuk
IvanPavliuk

Reputation: 1790

  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).

Upvotes: 2

Shriya Pandya
Shriya Pandya

Reputation: 432

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.

Upvotes: 0

Related Questions