在一张地图上显示多个谷歌地图标记和路线方向

4

我想在一个Google地图上输出多个谷歌地图路线。数据来自一个包含多个标记的XML文件。每个标记都有起点和终点(以纬度和经度值形式表示)。然后将这些标记添加到地图上,并调用Google地图方向服务以在每个标记的起点和终点之间绘制路径。

我的问题是只绘制了一条路线(如果刷新页面,似乎只会随机选择一个标记并画出两个标记之间的路线)。其他标记根本没有显示。

我已经使用console.log记录了for循环,以检查它是否对XML中的每个标记运行(是的),我猜测可能与这两行代码有关,但这只是一个猜测...

directionsDisplay = new google.maps.DirectionsRenderer();
directionsService = new google.maps.DirectionsService();

我看过这个问题 - 使用Google Maps 3 API在地图上获取多条路线,但我并不真正理解答案/不知道它与我的情况有多大关系。谢谢。

    jQuery(document).ready(function($) { 

    var map = new google.maps.Map(document.getElementById("map_canvas"), {
        zoom: 13,
        mapTypeId: 'roadmap'
    });

    // Try HTML5 geolocation
    if(navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(position) {
            var pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
            map.setCenter(pos);
            map.setZoom(13);
        }, function() {
            handleNoGeolocation(true);
        });
    } else {
        // Browser doesn't support Geolocation
        handleNoGeolocation(false);
    } 

    directionsDisplay = new google.maps.DirectionsRenderer();
    directionsService = new google.maps.DirectionsService();

    // Change this depending on the name of your PHP file
    downloadUrl("xml.php", function(data) {
        var xml = data.responseXML;
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
            var title = markers[i].getAttribute("title");
            mode = markers[i].getAttribute("mode");
            startpoint = new google.maps.LatLng(
                parseFloat(markers[i].getAttribute("startlat")),
                parseFloat(markers[i].getAttribute("startlng")));
            endpoint = new google.maps.LatLng(
                parseFloat(markers[i].getAttribute("endlat")),
                parseFloat(markers[i].getAttribute("endlng")));
            calcRoute();
            console.log('marker');
        }
    });
    directionsDisplay.setMap(map);

});


function calcRoute() {
    var request = {
        origin: startpoint,
        destination: endpoint,
        //waypoints: waypts,
        travelMode: google.maps.DirectionsTravelMode[mode]
    };
    directionsService.route(request, function(response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
            directionsDisplay.setDirections(response);
        }
    });
}

function downloadUrl(url, callback) {
    var request = window.ActiveXObject ?
    new ActiveXObject('Microsoft.XMLHTTP') :
    new XMLHttpRequest;

    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            request.onreadystatechange = doNothing;
            callback(request, request.status);
        }
    };

    request.open('GET', url, true);
    request.send(null);
}

function doNothing() {}
1个回答

4
我认为你链接的答案中的关键点是每个路线都需要自己的DirectionsRenderer对象。虽然它没有提到,但每个路线似乎也应该有自己的DirectionsService对象。您正在将这些对象之一与所有路线共享。我怀疑这些共享对象正在被每个路线覆盖。
这里是一个更新版本,通过为每个路线创建新的对象来修复此问题:
    jQuery(document).ready(function($) { 

    var map = new google.maps.Map(document.getElementById("map_canvas"), {
        zoom: 13,
        mapTypeId: 'roadmap'
    });

    // Try HTML5 geolocation
    if(navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(position) {
            var pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
            map.setCenter(pos);
            map.setZoom(13);
        }, function() {
            handleNoGeolocation(true);
        });
    } else {
        // Browser doesn't support Geolocation
        handleNoGeolocation(false);
    } 

    // Change this depending on the name of your PHP file
    $.get("xml.php", function( xml ) {
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
            addMarkerPair( markers[i] );
        }
    }, 'xml' );
});

function addMarkerPair( pair ) {
    function get( name ) {
        return pair.getAttribute( name );
    }
    var title = get("title");
    var mode = get("mode");
    var startpoint = new google.maps.LatLng(
        +get("startlat"),
        +get("startlng")
    );
    var endpoint = new google.maps.LatLng(
        +get("endlat"),
        +get("endlng")
    );
    calcRoute( mode, startpoint, endpoint );
    console.log('marker');
}

function calcRoute( mode, startpoint, endpoint ) {
    var directionsService = new google.maps.DirectionsService();
    var directionsDisplay = new google.maps.DirectionsRenderer();
    directionsDisplay.setMap(map);
    var request = {
        origin: startpoint,
        destination: endpoint,
        //waypoints: waypts,
        travelMode: google.maps.DirectionsTravelMode[mode]
    };
    directionsService.route(request, function(response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
            directionsDisplay.setDirections(response);
        }
    });
}

我还顺便修复和简化了一些东西:
  1. 将标记循环体移动到一个单独的 addMarkerPair 函数中,以提高可读性。
  2. addMarkerPair 中添加了一个 get 函数,作为 pair.getAttribute 的速记。
  3. 使用 + 代替 parseInt。两者都可以做同样的事情;我喜欢 + 的简洁性。
  4. 添加了几个缺少的 var 声明。
  5. 将所需参数作为函数参数传递给 calcRoute,而不是全局变量。
  6. 使用 $.get 代替 downloadUrl。当jQuery已经具备此功能时,您不需要自己的函数。

另外,作为解析XML的另一种选择,您可以使用jQuery访问XML元素。但我坚持使用更接近您当前操作方式的代码。


谢谢你的回答,Michael。我尝试了你的代码,但是在这一行出现了一个“Uncaught TypeError: Cannot read property 'documentElement' of undefined”的错误 - var markers = xml.documentElement.getElementsByTagName("marker"); 有什么想法吗? - GuerillaRadio
抱歉,我的错,我在将代码更改为使用$.get()而不是downloadUrl()时忘记了双重检查代码。我更新了代码以删除var xml = data.responseXML;,因为这不再需要,并在$.get()调用中添加了显式的“xml”数据类型(回调函数之后的最后一个参数)。如果您的服务器为XML文件设置了正确的MIME类型标头,则可能不需要该参数,但添加该参数可以确保jQuery为您解析XML。 - Michael Geary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接