如何在Xamarin Forms地图上绘制含3个以上途经点的路线Polyline
实现带途经点路线绘制的修改方案
Google Directions API原生支持waypoints参数传入途经点,你只需要调整现有请求和数据处理逻辑即可,大部分已有代码可以直接复用。
1. 修改API请求方法,支持传入途经点
调整GetDirections方法的入参,增加途经点列表,同时拼接请求URL时加入waypoints参数:
public async Task<GoogleDirection> GetDirections(string originLatitude, string originLongitude, string destinationLatitude, string destinationLongitude, List<(double Lat, double Lng)> waypoints = null) { try { GoogleDirection googleDirection = new GoogleDirection(); // 用StringBuilder拼接URL,方便动态加途经点 var urlBuilder = new StringBuilder($"api/directions/json?mode=driving&transit_routing_preference=less_driving&origin={originLatitude},{originLongitude}&destination={destinationLatitude},{destinationLongitude}"); // 存在途经点时拼接参数,用Uri转义避免特殊字符报错 if (waypoints != null && waypoints.Any()) { var waypointsStr = string.Join("|", waypoints.Select(wp => $"{wp.Lat},{wp.Lng}")); urlBuilder.Append($"&waypoints={Uri.EscapeDataString(waypointsStr)}"); } urlBuilder.Append($"&key={AppConstants.GoogleMapsApiKey}"); var response = await client.GetAsync(urlBuilder.ToString()).ConfigureAwait(false); if (response.IsSuccessStatusCode) { var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(json)) { googleDirection = await Task.Run(() => JsonConvert.DeserializeObject<GoogleDirection>(json) ).ConfigureAwait(false); } } return googleDirection; } catch (Exception ex) { Console.WriteLine(ex.Message); return null; } }
2. 调整路线数据处理逻辑,适配多段路线
多途经点的返回结果中Legs字段会包含多段路线(n个途经点对应n+1段路线),需要累加所有段的距离和时长,避免被最后一段数值覆盖:
// 提前定义单位里程费率,不要和总费用变量重名,避免逻辑错误 private const double UnitRouteRate = 0.001; // 示例:每米0.001元 public async Task<System.Collections.Generic.List<Xamarin.Forms.GoogleMaps.Position>> LoadRoutes() { try { // 提取途经点:routes列表第一个是起点,最后一个是终点,中间所有都是途经点 var waypoints = routes.Skip(1).Take(routes.Count - 2) .Select(r => (r.Latitude, r.Longitude)) .ToList(); // 调用修改后的GetDirections方法,传入途经点 var googleDirection = await ApiServices.ServiceClientInstance.GetDirections( Convert.ToString(routes[0].Latitude), Convert.ToString(routes[0].Longitude), Convert.ToString(routes.Last().Latitude), Convert.ToString(routes.Last().Longitude), waypoints); googleDirectionGlobal = googleDirection; if (googleDirection.Routes != null && googleDirection.Routes.Count > 0) { double totalDistance = 0; double totalDuration = 0; foreach (var item in googleDirection.Routes) { foreach (var leg in item.Legs) { totalDistance += leg.Distance.Value; totalDuration += leg.Duration.Value; } } // 格式化总距离、时长、计算总费用 RouteDistance = $"{Math.Round(totalDistance / 1000, 1)} km"; RouteDuration = $"{Math.Round(totalDuration / 60, 0)} 分钟"; RouteRate = totalDistance * UnitRouteRate; // 这里逻辑完全不用改,OverviewPolyline已经包含所有途经点的完整路线编码 var positions = Enumerable.ToList(PolylineHelper.Decode(googleDirection.Routes.First().OverviewPolyline.Points)); return positions; } else { await page.DisplayAlert("Alert", "Add your payment method inside the Google Maps console.", "Ok"); return null; } } catch (Exception ex) { Console.WriteLine(ex.Message); return null; } }
3. 路线绘制逻辑无需改动
你现有的Polyline绘制代码完全兼容多途经点场景,解码后的positions已经是包含所有途经点的完整路线坐标,直接赋值即可正常绘制。
额外注意事项
- Google Directions API基础配额最多支持8个途经点,超出需要升级计费方案
- 如果你需要系统自动优化途经点顺序减少总路程,可以在
waypoints参数值开头添加optimize:true|前缀 - 如果你不需要某个途经点必须停留,只需要路线经过该点附近,可以在途经点坐标前加
via:前缀,避免路线被强制拆分为多段
内容的提问来源于stack exchange,提问作者Kudakwashe Mundangepfupfu
相关产品推荐
相关产品推荐

