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

如何在.NET MAUI Blazor Hybrid中实现Google Maps导航功能

实现Google Maps实时导航的修改方案(Blazor物流应用)

你当前的代码仅渲染了两点间的静态路径,要实现实时导航(跟随用户位置、动态更新指引),需要补充实时位置跟踪、导航状态管理和交互控制,以下是具体修改步骤:


一、修正数据传递错误

当前C#端传递的origin是字符串格式,JS中访问origin.Latitude会报错,需改为传递结构化对象:

修改@code中的RequestLocationPermissionAndInitializeMap方法:

private async Task RequestLocationPermissionAndInitializeMap()
{
    var status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
    if (status == PermissionStatus.Granted)
    {
        var (location, locationFetchingError) = await locationService.GetCurrentLocationAsync();
        // 传递结构化对象而非字符串,避免JS解析错误
        var origin = new { Latitude = location.Latitude, Longitude = location.Longitude };
        var destination = new { Latitude = 59.337017307552195, Longitude = 18.05017354381474 };
        await JS.InvokeVoidAsync("initNavigation", origin, destination);
    }
    else
    {
        Console.WriteLine("位置权限被拒绝");
    }
}

二、添加实时导航核心功能

1. 更新HTML结构(添加控制按钮与信息面板)

<div class="card my-card">
    <div id="map2" style="width: 100%; height: 400px"></div>
    <!-- 导航控制按钮 -->
    <div class="p-2 d-flex gap-2">
        <button onclick="startNavigation()" class="btn btn-primary">开始导航</button>
        <button onclick="pauseNavigation()" class="btn btn-secondary">暂停</button>
        <button onclick="stopNavigation()" class="btn btn-danger">结束</button>
    </div>
    <!-- 实时导航信息 -->
    <div id="navigation-info" class="p-2">
        <p>剩余距离: <span id="remaining-distance">-</span></p>
        <p>剩余时间: <span id="remaining-time">-</span></p>
    </div>
    <!-- 导航步骤面板 -->
    <div id="directions-panel" class="p-2 border-top"></div>
</div>

2. 修改JS逻辑(添加位置跟踪与导航状态管理)

let map;
let directionsService;
let directionsRenderer;
let watchId; // 位置监听ID
let currentRoute; // 当前导航路线数据
let isNavigating = false;

window.initNavigation = function (origin, destination) {
    map = new google.maps.Map(document.getElementById("map2"), {
        zoom: 15,
        center: { lat: origin.Latitude, lng: origin.Longitude },
        disableDefaultUI: false, // 保留必要UI控件(如缩放)
        zoomControl: true,
        mapTypeControl: false,
        streetViewControl: false
    });

    directionsService = new google.maps.DirectionsService();
    directionsRenderer = new google.maps.DirectionsRenderer({
        map: map,
        suppressMarkers: false,
        panel: document.getElementById("directions-panel")
    });

    // 预先获取路线数据
    const request = {
        origin: origin,
        destination: destination,
        travelMode: google.maps.TravelMode.DRIVING
    };

    directionsService.route(request, function (result, status) {
        if (status === google.maps.DirectionsStatus.OK) {
            directionsRenderer.setDirections(result);
            currentRoute = result;
            showNavigationSteps(result);
            updateNavigationInfo(result);
        } else {
            console.error("路线请求失败: " + status);
        }
    });
}

// 开始实时导航
function startNavigation() {
    if (isNavigating || !currentRoute) return;
    isNavigating = true;

    // 高精度监听位置变化
    watchId = navigator.geolocation.watchPosition(
        (position) => {
            const currentLatLng = new google.maps.LatLng(
                position.coords.latitude,
                position.coords.longitude
            );
            // 地图跟随当前位置
            map.panTo(currentLatLng);
            // 更新当前导航步骤
            updateCurrentStep(currentLatLng);
        },
        (error) => {
            console.error("位置跟踪失败: " + error.message);
            stopNavigation();
        },
        {
            enableHighAccuracy: true,
            timeout: 5000,
            maximumAge: 0
        }
    );
}

// 暂停导航
function pauseNavigation() {
    if (!isNavigating) return;
    navigator.geolocation.clearWatch(watchId);
    isNavigating = false;
}

// 结束导航
function stopNavigation() {
    if (watchId) {
        navigator.geolocation.clearWatch(watchId);
        watchId = null;
    }
    isNavigating = false;
}

// 更新实时导航信息
function updateNavigationInfo(result) {
    const leg = result.routes[0].legs[0];
    document.getElementById("remaining-distance").textContent = leg.distance.text;
    document.getElementById("remaining-time").textContent = leg.duration.text;
}

// 高亮当前所在导航步骤
function updateCurrentStep(currentLatLng) {
    const steps = currentRoute.routes[0].legs[0].steps;
    // 从后往前遍历,找到距离当前位置最近的步骤(误差50米内)
    for (let i = steps.length - 1; i >= 0; i--) {
        const stepLatLng = steps[i].end_location;
        const distance = google.maps.geometry.spherical.computeDistanceBetween(
            currentLatLng,
            stepLatLng
        );
        if (distance < 50) {
            const panelItems = document.getElementById("directions-panel").children;
            Array.from(panelItems).forEach((item, index) => {
                item.style.backgroundColor = index === i ? "#e3f2fd" : "transparent";
            });
            break;
        }
    }
}

function showNavigationSteps(directionResult) {
    const steps = directionResult.routes[0].legs[0].steps;
    const directionsPanel = document.getElementById("directions-panel");
    directionsPanel.innerHTML = "";

    steps.forEach((step, index) => {
        const instructionElement = document.createElement("div");
        instructionElement.className = "p-1 mb-1";
        instructionElement.innerHTML = `${index + 1}. ${step.instructions}`;
        directionsPanel.appendChild(instructionElement);
    });
}

三、关键注意事项

  • 需在Google Maps脚本引入时添加Geometry库(用于距离计算):
    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry"></script>
    
  • 位置跟踪仅在HTTPS环境下生效(本地localhost可正常测试)。
  • 可根据需求自定义用户位置标记(替换Google默认标记)。

内容的提问来源于stack exchange,提问作者Ayesh Nipun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 08:57:03