如何使用Google地图指导服务找到最近的标记?

时间:2016-02-26 13:07:39

标签: javascript angularjs google-maps ionic-framework

我正在开发一个谷歌地图项目,我正在填充谷歌地图,标记是从数据库中读取的(drawMarkers函数)。除此之外,谷歌地图会找到您当前的位置并每隔几秒钟保持刷新,以便在地图上跟踪您。我的问题是,最近的var也是我正在使用的函数,也找到最近的标记,然后从那里创建到当前位置的方向。我不知道如何实际找到最接近的标记,所以我从堆栈溢出中借用了另一个问题的代码,并试图使其适应这个项目。我需要帮助才能找到最近的标记,然后将其作为服务方向的目的地

$ionicSideMenuDelegate.canDragContent(false);

$scope.getTourMarkers = function () {
    tourmarkers.getTourMarkers().success(function (data) {
        $scope.tourmarkers = data;
        console.log($scope.tourmarkers);
        drawMarkers();
    });
};


var drawMarkers = function () {

    var markers;
    var content;
    var infoWindow;


    for (var i = 0; i < $scope.tourmarkers.length; i++) {
        content = '<h2>' + $scope.tourmarkers[i].title + '</h2>' +
            '<br />' +
            '<p>' +

            '</p>';

        infoWindow = new google.maps.InfoWindow({
            content: content
        });

        var point = new google.maps.LatLng($scope.tourmarkers[i].lat, $scope.tourmarkers[i].lon);

        markers = new google.maps.Marker({
            label: "S",
            animation: google.maps.Animation.DROP,
            position: point,
            map: map,
            info: content
    });

        //SCOPE: 'this' refers to the current 'markers' object, we pass in the info and marker
        google.maps.event.addListener(markers, 'click', function () {
            infoWindow.setContent(this.info);
            infoWindow.open(map, this);
        });
    }

};

var myLatlng = new google.maps.LatLng(38.5602, -121.4241);
var NAPA_HALL_LAT_LNG = new google.maps.LatLng(38.553801, -121.4212745); // just created this marker for testing purposes

var mapOptions = {
    center: myLatlng,
    zoom: 18,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    zoomControl: true,
    disableDefaultUI: true
};

var map = new google.maps.Map(document.getElementById("map"), mapOptions);

var marker = new google.maps.Marker({
    position: myLatlng,
    map: map,
    title: 'SAC STATE'
});

var dest = new google.maps.Marker({
    position: NAPA_HALL_LAT_LNG,
    map: map,
    title: 'NAPA HALL'
});

///////////////////Directions Display//////////////////////
var directionsDisplay = new google.maps.DirectionsRenderer;
var directionsService = new google.maps.DirectionsService;


//////////////////////////////////////////////////////////////////////////////////////////
//Goal of this function is to find closest marker to current location
//then to create directions to that marker.
//should be refreshed everytime in the onSuccess function
var closest = function (directionsService, directionsDisplay, marker, dest) {

    var event;

    function rad(x) {return x*Math.PI/180;}

    function find_closest_marker( event ) {
        var lat = event.latLng.lat();
        var lng = event.latLng.lng();
        var R = 6371;                           // radius of earth in km
        var distances = [];
        var shortest = -1;


        for( i=0;i < $scope.tourmarkers.length; i++) {
        content = '<h2>' + $scope.tourmarkers[i].title + '</h2>' +
            '<br />' +
            '<p>' +

            '</p>';

        infoWindow = new google.maps.InfoWindow({

        var mlat = $scope.tourmarkers[i].position.lat();
        var mlng = $scope.tourmarkers[i].position.lng();
        var dLat  = rad(mlat - lat);
        var dLong = rad(mlng - lng);
        var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(rad(lat)) * Math.cos(rad(lat)) * Math.sin(dLong/2) * Math.sin(dLong/2);
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        var d = R * c;
        distances[i] = d;
        if ( shortest == -1 || d < distances[shortest] ) {
            shortest = i;
        }
    }

    alert(map.markers[shortest].title);
}

    /////**directions feature should have the closest marker be the desitination//
    directionsService.route({
        origin: marker.position,  
        destination: dest.position,               // i think the marker that should in here is shortest.
        travelMode: google.maps.TravelMode.WALKING
    }, function(response,status) {
        if(status==google.maps.DirectionsStatus.OK) {
            directionsDisplay.setDirections(response);
        } else {
            window.alert('Directions request failed due to ' + status);
        }
    });
};
//////////////////////////////////////////////////////////////////////////////////////////  

var onSuccess = function (position) {

    marker.setPosition(new google.maps.LatLng(position.coords.latitude, position.coords.longitude));
    directionsDisplay.setMap(map);
    dest.setPosition(new google.maps.LatLng(38.553801, -121.4212745));
    //dest.setPosition((closest(marker, $scope.tourmarkers)).position);  // if you can get this line to work without commenting it out then you're set
    closest(directionsService,directionsDisplay, marker,dest);
    $scope.map = map;
    //$scope.map.panTo(new google.maps.LatLng(position.coords.latitude, position.coords.longitude));
};

function onError(error) {
    alert('code: ' + error.code + '\n' +
        'message: ' + error.message + '\n');
}

navigator.geolocation.watchPosition(onSuccess, onError, {
    maximumAge: 3000,
    timeout: 5000,
    enableHighAccuracy: true
});

除了最接近的功能外,该项目中的所有内容都正常工作。但即便如此,我已经测试了方向服务,甚至那也是有效的。我只需要帮助使方向服务中的目的地成为最接近当前位置的标记。

1 个答案:

答案 0 :(得分:-1)

我认为此代码对您有帮助我在项目中使用此代码,以使您的要求与我的要求相同

在下面的函数'data'中表示来自服务器的lat lng列表

function initialize(data) {
    size = 0;
    counts = 0;
    stops = data;
    size = stops.length;

        if (stops.length > 0) {
            var map = new window.google.maps.Map(document
                    .getElementById("map"));
            // new up complex objects before passing them around
            var directionsDisplay = new window.google.maps.DirectionsRenderer(
                    {
                        suppressMarkers : true,
                        polylineOptions : {
                            strokeColor : "black"
                        }
                    });
            var directionsService = new window.google.maps.DirectionsService();
            Tour_startUp(stops);
            window.tour.loadMap(map, directionsDisplay);
            window.tour.fitBounds(map,stops);
            /* if (stops.length > 1) */
                window.tour.calcRoute(stops,directionsService,
                        directionsDisplay,size);
        }
}


function Tour_startUp(stops) {
    var stops=stops;
    var counts=0;
    if (!window.tour) window.tour = {
        // map: google map object
        // directionsDisplay: google directionsDisplay object (comes in empty)
        loadMap: function (map, directionsDisplay) {
            var myOptions = {
                zoom:10,
                center: new window.google.maps.LatLng(17.379818, 78.478542), // default to Hyderabad
                mapTypeId: window.google.maps.MapTypeId.ROADMAP
            };
            map.setOptions(myOptions);
            directionsDisplay.setMap(map);
        },
        fitBounds: function (map,stops) {
            var bounds = new window.google.maps.LatLngBounds();
            // extend bounds for each record

            jQuery.each(stops, function (key, val) {
                var myLatlng = new window.google.maps.LatLng(val.latitude, val.longitude);
                bounds.extend(myLatlng);
            });
            map.fitBounds(bounds);

        },
        calcRoute: function (stops,directionsService, directionsDisplay,size) {
            size=size;
            var batches = [];
            var itemsPerBatch = 10; // google API max = 10 - 1 start, 1 stop, and 8 waypoints
            var itemsCounter = 0;
            var wayptsExist = stops.length > 0;
            var tempp=0;
            while (wayptsExist) {
                var subBatch = [];
                var subitemsCounter = 0;

                for (var j = itemsCounter; j < stops.length; j++) {
                    subitemsCounter++;
                    tempp++;
                    subBatch.push({

                        location: new window.google.maps.LatLng(stops[j].latitude, stops[j].longitude),
                        stopover: true
                    });
                    if (subitemsCounter == itemsPerBatch)
                        break;
                }
                itemsCounter += subitemsCounter;
                batches.push(subBatch);
                wayptsExist = itemsCounter < stops.length;
                // If it runs again there are still points. Minus 1 before continuing to
                // start up with end of previous tour leg
                itemsCounter--;
            }

            // now we should have a 2 dimensional array with a list of a list of waypoints
            var combinedResults;
            var unsortedResults = [{}]; // to hold the counter and the results themselves as they come back, to later sort
            var directionsResultsReturned = 0;

            for (var k = 0; k < batches.length; k++) {
                var lastIndex = batches[k].length - 1;
                var start = batches[k][0].location;
               //delay(600); 
                var end = batches[k][lastIndex].location;


                // trim first and last entry from array
                var waypts = [];
                waypts = batches[k];
                waypts.splice(0, 1);
                waypts.splice(waypts.length - 1, 1);

                var request = {
                    origin: start,
                    destination: end,
                    waypoints: waypts,
                    travelMode: window.google.maps.TravelMode.WALKING
                };
                (function (kk) {
                    directionsService.route(request, function (result, status) {
                        if (status == window.google.maps.DirectionsStatus.OK) {
                            var unsortedResult = { order: kk, result: result };
                            unsortedResults.push(unsortedResult);
                            //alert("count test");
                            directionsResultsReturned++;
                            if (directionsResultsReturned == batches.length) // we've received all the results. put to map
                            {
                                // sort the returned values into their correct order
                                unsortedResults.sort(function (a, b) { return parseFloat(a.order) - parseFloat(b.order); });
                                var count = 0;
                                for (var key in unsortedResults) {
                                    if (unsortedResults[key].result != null) {
                                        if (unsortedResults.hasOwnProperty(key)) {
                                            if (count == 0) // first results. new up the combinedResults object
                                                combinedResults = unsortedResults[key].result;
                                            else {
                                                // only building up legs, overview_path, and bounds in my consolidated object. This is not a complete
                                                // directionResults object, but enough to draw a path on the map, which is all I need
                                                combinedResults.routes[0].legs = combinedResults.routes[0].legs.concat(unsortedResults[key].result.routes[0].legs);
                                                combinedResults.routes[0].overview_path = combinedResults.routes[0].overview_path.concat(unsortedResults[key].result.routes[0].overview_path);

                                                combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getNorthEast());
                                                combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getSouthWest());
                                            }
                                            count++;
                                        }
                                    }
                                }
                                directionsDisplay.setDirections(combinedResults);
                                var legs = combinedResults.routes[0].legs;
                                var summaryPanel = document.getElementById('directions_panel');
                                summaryPanel.innerHTML = '';
                                var totdist=0;
                                for (var i=0; i < legs.length;i++){

                                     var markerletter = "A".charCodeAt(0);
                                     var markerletter2= "B".charCodeAt(0)
                                         markerletter += i;
                                    markerletter2 += i; 
                                  markerletter = String.fromCharCode(markerletter);
                                  markerletter2 = String.fromCharCode(markerletter2);
                                  createMarker(directionsDisplay.getMap(),legs[i].start_location,legs[i].start_address,markerletter,size);//To display location address on the marker
                                  var routeSegment = i + 1;
                                  var point=+routeSegment+1;
                                  summaryPanel.innerHTML += '<b>Route Segment: ' + routeSegment + '</b><br>';
                                  summaryPanel.innerHTML += '<b>Point '+ routeSegment +' :</b>'+ '  ' +legs[i].start_address + ' <br> ';
                                  summaryPanel.innerHTML += '<b>Point '+ point +' :</b>'+ '  '+legs[i].end_address + '<br>';
                                  summaryPanel.innerHTML += '<b>Distance Covered '+' :</b>'+legs[i].distance.text + '<br><br>';
                                  var test=legs[i].distance.text.split(' ');
                                  var one=parseFloat(test[0]);
                                if(test[1]=="m"){
                                  var one=parseFloat(test[0]/1000); 
                                  }
                                  totdist=parseFloat(totdist)+parseFloat(one);
                                }
                                summaryPanel.innerHTML += '<b> Total Distance :'+totdist + 'km'+ '</b><br><br>';
                                var i=legs.length;
                                var markerletter = "A".charCodeAt(0);
                    markerletter += i;
                                markerletter = String.fromCharCode(markerletter);
                                createMarker(directionsDisplay.getMap(),legs[legs.length-1].end_location,legs[legs.length-1].end_address,markerletter,size);
                            }
                        }
                    });
                })(k);
                function delay(ms) {
                       ms += new Date().getTime();
                       while (new Date() < ms){}
                    }
            }
        }//calculate route end
    };
}



//to show information on clicking marker
var infowindow = new google.maps.InfoWindow(
  { 
    size: new google.maps.Size(150,50)
  }); 


var icons = new Array();
icons["red"] = new google.maps.MarkerImage("mapIcons/marker_red.png",
      // This marker is 20 pixels wide by 34 pixels tall.
      new google.maps.Size(20, 34),
      // The origin for this image is 0,0.
      new google.maps.Point(0,0),
      // The anchor for this image is at 9,34.
      new google.maps.Point(9, 34));



function getMarkerImage(iconStr,size) {
    counts++;
     if(counts==size){
        var markerimageLoc = "http://www.maps.google.com/mapfiles/ms/icons/blue.png";
        counts = 0;
    }else{
   if (iconStr=="undefined") { 
      iconStr = "red"; 
      var markerimageLoc = "http://www.maps.google.com/mapfiles/ms/icons/red.png"; 
   }
   else{
        var markerimageLoc="http://www.google.com/mapfiles/marker"+ iconStr +".png"; 
      //  var markerimageLoc = "http://www.maps.google.com/mapfiles/ms/icons/red.png";   
   }
    }
      icons[iconStr] = new google.maps.MarkerImage(markerimageLoc,
      // This marker is 20 pixels wide by 34 pixels tall.
      new google.maps.Size(25, 34),
      // The origin for this image is 0,0.
      new google.maps.Point(0,0),
      // The anchor for this image is at 6,20.
      new google.maps.Point(9, 34));
   return icons[iconStr];

}
  // Marker sizes are expressed as a Size of X,Y
  // where the origin of the image (0,0) is located
  // in the top left of the image.

  // Origins, anchor positions and coordinates of the marker
  // increase in the X direction to the right and in
  // the Y direction down.

  var iconShadow = new google.maps.MarkerImage('http://www.google.com/mapfiles/shadow50.png',
      // The shadow image is larger in the horizontal dimension
      // while the position and offset are the same as for the main image.
      new google.maps.Size(37, 34),
      new google.maps.Point(0,0),
      new google.maps.Point(9, 34));
      // Shapes define the clickable region of the icon.
      // The type defines an HTML &lt;area&gt; element 'poly' which
      // traces out a polygon as a series of X,Y points. The final
      // coordinate closes the poly by connecting to the first
      // coordinate.
  var iconShape = {
      coord: [9,0,6,1,4,2,2,4,0,8,0,12,1,14,2,16,5,19,7,23,8,26,9,30,9,34,11,34,11,30,12,26,13,24,14,21,16,18,18,16,20,12,20,8,18,4,16,2,15,1,13,0],
      type: 'poly'
  };

function createMarker(map, latlng, label, character,size) {
        var markerletter = character;
        var size=size;
         if (/[^a-zA-Z]/.test(character)) {
            var markerletter = "undefined";
        }
        var contentString = '<b>' + label + '</b><br>';
        var marker = new google.maps.Marker({
            position : latlng,
            map : map,
            shadow : iconShadow,
            icon : getMarkerImage(markerletter,size),
            shape : iconShape,
            title : label,
            zIndex : Math.round(latlng.lat() * -100000) << 5
        });
        marker.myname = label;

        google.maps.event.addListener(marker, 'click', function() {
            infowindow.setContent(contentString);
            infowindow.open(map, marker);
        });
        return marker;
    }