3

タイトルのように: マーカーがドラッグされているときに道路にスナップするポリラインを実装する方法は? 答えを探すのに多くの時間を費やしましたが、もう諦めました。DirectionsRenderer なしで可能であれば、DirectionsService のみを使用したいと思います。以下は、スナップがそれぞれではなく、最後のマーカーとパスに対してのみ機能する、クリーンなバージョンのコードです。助けていただければ幸いです。

jsfiddleとここの私のコード:

var map,
path = [],
    markers = [],
    directionsService = new google.maps.DirectionsService(),
    poly;

function addMarker(p) {
    var marker = new google.maps.Marker({
        position: p,
        map: map,
        draggable: true
    });
    markers.push(marker);

    google.maps.event.addListener(marker, "drag", function () {
        var request = {
            origin: path[path.length - 1],
            destination: marker.getPosition(),
            travelMode: google.maps.DirectionsTravelMode.DRIVING
        };
        directionsService.route(request, function (response, status) {
            if (status == google.maps.DirectionsStatus.OK) {
                marker.setPosition(response.routes[0].legs[0].end_location);
                path = path.concat(response.routes[0].overview_path);
                poly.setPath(path);
            }
        });
    });
}

function initialize() {
    var myOptions = {
        zoom: 17,
        center: new google.maps.LatLng(40.7143528, -74.00597310000001),
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        draggableCursor: "crosshair"
    }

    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

    google.maps.event.addListener(map, 'click', function (event) {

        if (path.length == 0) {
            path.push(event.latLng);
            poly = new google.maps.Polyline({
                map: map
            });
            poly.setPath(path);
            addMarker(event.latLng);
        } else {
            var request = {
                origin: path[path.length - 1],
                destination: event.latLng,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
            };
            directionsService.route(request, function (response, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    addMarker(response.routes[0].legs[0].end_location);

                    path = path.concat(response.routes[0].overview_path);
                    poly.setPath(path);
                }
            });
        }
    });
}
4

1 に答える 1

3

これは、以下のコードに記載されている理由により、優れたパフォーマンスを維持しながら実装するのはかなり難しいことです。マーカーをドラッグしながら道路にスナップすることを要求しますが、これを行うには制限と問題があります。ドラッグ中に道路にスナップせずに、マーカー ドラッグの終了時にこれを行うコードを提供します。以下のコードの 1 行のコメントを解除すると、必要に応じてドラッグ中に道路にスナップできるようになりますが、以下に示す理由により、これはお勧めしません。ここで私のコードの終わりに向かってコメントを見て、ここで実際に見ることができますhttp://jsfiddle.net/VvR5k/1/

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Some Title</title>
</head>
<body>
<p>Click on map to place markers, drag markers to change route</p>
<p>Please view comment block towards end of javascript code!</p>
<p><button type="button" onclick="resetMarkers();">Reset Markers</button></p>
<div id="map_canvas" style="width:800px; height:600px;">
</div>
<script src="http://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script type="text/javascript">

function init() {
    var markers = [],
        segments = [],
        myOptions = {
            zoom: 12,
            center: new google.maps.LatLng(34.0504, -118.2444),
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            disableDoubleClickZoom: true,
            draggableCursor: "crosshair"
        },
        alphas = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
        alphaIdx = 0,
        map = new google.maps.Map(document.getElementById("map_canvas"), myOptions),
        service = new google.maps.DirectionsService(),
        poly = new google.maps.Polyline({
            map: map,
            strokeColor: '#00FFFF',
            strokeOpacity: 0.6,
            strokeWeight: 5
    });
    window.resetMarkers = function () {
        for (var i = 0; i < markers.length; i++) {
            markers[i].setMap(null);
        }
        alphaIdx = 0;
        segments = [];
        markers = [];
        poly.setPath([]);
    };
    function getSegmentsPath() {
        var a, i,
            len = segments.length,
            arr = [];
        for (i = 0; i < len; i++) {
            a = segments[i];
            if (a && a.routes) {
                arr = arr.concat(a.routes[0].overview_path);
            }
        }
        return arr;
    }

    function addSegment(start, end, segIdx) {
        service.route(
            {
                origin: start,
                destination: end,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
            },
            function (result, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    //store the entire result, as we may at some time want
                    //other data from it, such as the actual directions
                    segments[segIdx] = result;
                    poly.setPath(getSegmentsPath());
                }
            }
        );
    }
    google.maps.event.addListener(map, "click", function (e) {
        //limiting the number of markers added to no more than 26, as if we have
        //that many we have used up all our alphabetical characters for the icons
        if (alphaIdx > 25) {
            return;
        }
        var evtPos = e.latLng,
            c = alphas[alphaIdx++],
            marker = new google.maps.Marker({
                map: map,
                position: evtPos,
                draggable: true,
                icon: 'http://www.google.com/mapfiles/marker'+ c +'.png'
        });
        marker.segmentIndex = markers.length - 1;
        marker.iconChar = c;//just storing this for good measure, may want at some time
        function updateSegments() {
            var start, end, inserts, i,
                idx = this.segmentIndex,
                segLen = segments.length, //segLen will always be 1 shorter than markers.length
                myPos = this.getPosition();
            if (segLen === 0) { //nothing to do, this is the only marker
                return;
            }
            if (idx == -1) { //this is the first marker
                start = [myPos];
                end = [markers[1].getPosition()];
                inserts = [0];
            } else if (idx == segLen - 1) { //this is the last marker
                start = [markers[markers.length - 2].getPosition()];
                end = [myPos];
                inserts = [idx];
            } else {//there are markers both behind and ahead of this one in the 'markers' array
                start = [markers[idx].getPosition(), myPos];
                end = [myPos, markers[idx + 2].getPosition()];
                inserts = [idx, idx + 1];
            }
            for (i = 0; i < start.length; i++) {
                addSegment(start[i], end[i], inserts[i]);
            }
        }
        /**********************************************************************
        Note that the line below which sets an event listener for the markers
        'drag' event and which is commented out (uncomment it to test,
        but I do not recommend using it in reality) causes us to constantly
        poll google for DirectionsResult objects and may perform poorly at times
        while a marker is being dragged, as the application must wait for a
        directions request to be sent and received from google many many many
        times while the marker is dragged. For these reasons, I personally would
        only use the dragend event listener. Additionally, using the below line can
        very quickly run you up against google maps api services usage limit of
        2500 directions requests per day, as while a marker is being dragged it
        could cause hundreds and hundreds of directions requests to be made! Not good!
        see about usage limits: https://developers.google.com/maps/documentation/directions/#Limits
        ***********************************************************************/
        //google.maps.event.addListener(marker, 'drag', updateSegments);
        google.maps.event.addListener(marker, 'dragend', updateSegments);
        markers.push(marker);
        if (markers.length > 1) {
            addSegment(markers[markers.length - 2].getPosition(), evtPos, marker.segmentIndex);
        }
    });
}
init();

</script>
</body>
</html>
于 2013-05-12T12:33:45.297 に答える