You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 19:36:03