如何在一张 Google 地图上显示 Flutter 中的多组折线
How to show multiple sets of polylines in Flutter on one Google map
我正在尝试显示多组不同的折线(每组代表一条具有自己起点和终点的自行车路线)。
我从 JSON
文件中引入了总共十条路线。问题是 map
正在将所有单独的十条路线合并为一条巨大的折线。
所以它有点把它们连接在一起(你可以找出每条路线之间的直线连接,只有一个 startCap
和 endCap
图标)。
我会 expect/want 看到十个不同的 startCap
和 endCap
图标以及 每个折线集之间 的空格。
那么如何让 map
将每条折线路线显示为不同的路线?
我正在使用 flutter_polyline_points
解码通往 google map
的折线路线。
下面的代码和 JSON
已上线 link 如果有帮助,可以轻松模拟。
本质上步骤:
我创建了 google 地图,上面有一个主要的中央标记。
然后我从 JSON
文件中引入十个路由。这些是名为 Segments 的数组中的十个对象。每个对象都有我用于 PolyLineid
的唯一 ID 和字符串中一组唯一的折线点。所以我引入了 JSON
然后.
遍历每个对象并将多段线字符串解码为多段线坐标,然后我尝试将其作为多条多段线添加到地图中。
这里还有我看到的输出,使问题栩栩如生。
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();
},
),
),
);
}
}
JSON 文件内容(在代码中的 link 上) https://ibikeride.com/strava.json 供参考:
{
"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.
我在 Medium 上搜索了很多次这个问题,并且看了没完没了的 youtube 视频,但仍然一头雾水。任何指点表示赞赏。
我感觉这与创建一个 list
独特的 Polyines 迭代添加有关。非常感谢
您必须创建包含经纬度的对象列表。将折线坐标和标记添加到列表中。如 link.
中所示
创建一个生成折线的方法:
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;
}
生成任意数量的折线:
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;
}
将生成的折线设置为GoogleMap
(polylines
字段)。
我正在尝试显示多组不同的折线(每组代表一条具有自己起点和终点的自行车路线)。
我从 JSON
文件中引入了总共十条路线。问题是 map
正在将所有单独的十条路线合并为一条巨大的折线。
所以它有点把它们连接在一起(你可以找出每条路线之间的直线连接,只有一个 startCap
和 endCap
图标)。
我会 expect/want 看到十个不同的 startCap
和 endCap
图标以及 每个折线集之间 的空格。
那么如何让 map
将每条折线路线显示为不同的路线?
我正在使用 flutter_polyline_points
解码通往 google map
的折线路线。
下面的代码和 JSON
已上线 link 如果有帮助,可以轻松模拟。
本质上步骤:
我创建了 google 地图,上面有一个主要的中央标记。
然后我从
JSON
文件中引入十个路由。这些是名为 Segments 的数组中的十个对象。每个对象都有我用于PolyLineid
的唯一 ID 和字符串中一组唯一的折线点。所以我引入了JSON
然后.遍历每个对象并将多段线字符串解码为多段线坐标,然后我尝试将其作为多条多段线添加到地图中。
这里还有我看到的输出,使问题栩栩如生。
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();
},
),
),
);
}
}
JSON 文件内容(在代码中的 link 上) https://ibikeride.com/strava.json 供参考:
{
"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.
我在 Medium 上搜索了很多次这个问题,并且看了没完没了的 youtube 视频,但仍然一头雾水。任何指点表示赞赏。
我感觉这与创建一个 list
独特的 Polyines 迭代添加有关。非常感谢
您必须创建包含经纬度的对象列表。将折线坐标和标记添加到列表中。如 link.
中所示创建一个生成折线的方法:
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; }
生成任意数量的折线:
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; }
将生成的折线设置为
GoogleMap
(polylines
字段)。