如何使用google_maps_flutter Flutter包展示已保存的编码地图路线及导航指引?
实现已保存路线展示+自定义导航指引的方案
首先得明确:目前没有现成的Flutter包能直接加载你保存的路线编码,同时提供像谷歌地图APP那样的原生导航指引。但我们可以通过两种思路来实现你的需求,下面详细说明:
方案1:解析路线编码,自行实现导航指引逻辑
这种方式适合你只保存了Polyline编码字符串的情况,核心是自己处理位置匹配和指引生成:
步骤1:解码路线并绘制Polyline
先用polyline解码包(比如polyline_encoder)把你保存的编码字符串转成坐标列表,再用google_maps_flutter画出路线:
import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:polyline_encoder/polyline_encoder.dart'; List<LatLng> decodeSavedRoute(String encodedPolyline) { final decodedPoints = PolylineDecoder.decodePolyline(encodedPolyline); return decodedPoints.map((p) => LatLng(p.latitude, p.longitude)).toList(); } // 在GoogleMap的polylines中使用 Set<Polyline> _polyline = { Polyline( polylineId: const PolylineId("saved_route"), points: decodeSavedRoute(yourEncodedString), color: Colors.blue, width: 5, ) };
步骤2:实时匹配位置并生成指引
使用geolocator获取用户实时位置,结合地理计算包(比如latlong2)来判断用户在路线上的位置,进而生成导航提示:
- 先把解码后的路线坐标拆分成路段(比如每两个连续坐标点为一段)
- 计算用户当前位置到各路段的距离,找到最近的路段
- 定位到下一个转弯点(如果你的路线编码包含转弯点信息,或者你保存路线时额外记录了转弯坐标),计算距离和方向,生成类似“前行300米左转”的提示
示例代码片段:
import 'package:geolocator/geolocator.dart'; import 'package:latlong2/latlong.dart'; // 监听位置变化 void startLocationTracking(List<LatLng> routePoints) { Geolocator.getPositionStream( locationSettings: const LocationSettings(accuracy: LocationAccuracy.high), ).listen((position) { final currentLatLng = LatLng(position.latitude, position.longitude); final distanceCalculator = Distance(); // 找到离用户最近的路线点 LatLng nearestPoint = routePoints.first; double minDistance = double.infinity; for (var point in routePoints) { final distance = distanceCalculator.as( LengthUnit.Meter, LatLng(currentLatLng.latitude, currentLatLng.longitude), LatLng(point.latitude, point.longitude), ); if (distance < minDistance) { minDistance = distance; nearestPoint = point; } } // 假设下一个转弯点是routePoints中的第N个点,这里需要你根据保存的路线逻辑判断 final nextTurnPoint = routePoints[routePoints.indexOf(nearestPoint) + 5]; final distanceToTurn = distanceCalculator.as( LengthUnit.Meter, currentLatLng, nextTurnPoint, ); // 生成指引文本(这里的转弯方向需要根据路线走向判断,你可以通过计算方位角实现) setState(() { currentNavigationHint = "前行${distanceToTurn.round()}米后左转"; }); }); }
方案2:保存完整路线步骤,配合位置展示指引
如果你最初是通过Google Maps Directions API生成的路线,建议不仅保存Polyline编码,还要保存完整的路线steps数据(包含每个路段的指引文本、距离、起止坐标等)。这样后续可以直接复用这些steps来展示导航提示:
步骤1:保存路线时记录Steps
调用Directions API后,把DirectionsResponse中的legs[0].steps序列化(比如转成JSON)存入数据库:
// 假设你通过google_maps_webservice获取路线 import 'package:google_maps_webservice/directions.dart'; final directions = GoogleMapsDirections(apiKey: "YOUR_API_KEY"); final response = await directions.directions( Location(originLat, originLng), Location(destLat, destLng), ); // 保存steps到数据库 final savedStepsJson = jsonEncode(response.routes.first.legs.first.steps); // 存入数据库...
步骤2:加载Steps并匹配位置展示指引
从数据库取出steps数据,反序列化为对象,然后监听用户位置,判断当前处于哪个step,直接展示对应的指引文本:
// 从数据库取出并反序列化steps List<Step> savedSteps = (jsonDecode(savedStepsJson) as List) .map((e) => Step.fromJson(e)) .toList(); // 监听位置,匹配当前step Geolocator.getPositionStream().listen((position) { final currentLoc = LatLng(position.latitude, position.longitude); final distanceCalculator = Distance(); // 找到当前用户所在的step Step currentStep = savedSteps.firstWhere((step) { final startDistance = distanceCalculator.as( LengthUnit.Meter, currentLoc, LatLng(step.startLocation.lat, step.startLocation.lng), ); final endDistance = distanceCalculator.as( LengthUnit.Meter, currentLoc, LatLng(step.endLocation.lat, step.endLocation.lng), ); // 判断用户是否在当前step的路段范围内 return startDistance < 100 && endDistance < 300; }); // 直接展示API返回的指引文本 setState(() { currentNavigationHint = currentStep.instructions; }); });
局限性说明
- 自行实现的导航指引无法完全媲美谷歌地图APP的原生体验,比如处理路线偏离后的重新规划、复杂路口的可视化指引等,都需要额外开发逻辑。
- 如果你想用谷歌地图APP的原生导航功能,目前无法加载自定义的已保存路线——因为谷歌地图APP的导航是基于实时路况计算的最优路线,不支持导入外部路线数据。
内容的提问来源于stack exchange,提问作者Ajantha Bandara
相关产品推荐
相关产品推荐

