Reputation: 72
I am trying to get the nearest marker to the user location and then get directions on button click, I have passed the markers to getDirections(markers)
but when the function google.maps.geometry.spherical.computeDistanceBetween
takes the google.maps.LatLng
object throws the error Uncaught TypeError: Cannot read property 'lat' of undefined
But the markers array and the userLocation are both OK with the data (not undefined) so I can't understand what is going on.
The code:
jQuery(document).ready(function () {
// Create the script tag, set the appropriate attributes
let script = document.createElement('script');
script.src = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyBMCq6Fj4pN0Ku5ScVza28FZw0beM&callback=initMap&libraries=places&libraries=geometry';
script.defer = true;
var map
let infowindow
window.initMap = function () {
const center = {
lat: -36.561551,
lng: -72.0954877
}
infowindow = new google.maps.InfoWindow();
map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: center
});
let markers = setMarkers(map)
getDirections(markers)
}
const locations = [
['Super Pellet Santiago', -33.458717664930084, -70.77513497336462],
['Super Pellet Chillan', -36.561551, -72.0954877],
['Super Pellet Concepción', -36.8158124, -73.0741686],
['Super Pellet Los Angeles', -37.4774907, -72.3245759],
['Super Pellet Angol', -33.80010128657071, 151.28747820854187],
['Super Pellet Temuco', -38.7702088, -72.6301967]
];
function setMarkers(map) {
let markers = []
for (let i = 0; i < locations.length; i++) {
markers[i] = new google.maps.Marker({
title: locations[i][0],
position: {
lat: locations[i][1],
lng: locations[i][2]
},
map: map
});
google.maps.event.addListener(markers, 'click', (function (markers, i) {
return function () {
infowindow.setContent(locations[i][0]);
infowindow.open(map, markers);
}
})(markers, i));
}
return markers
// Append the 'script' element to 'head'
}
document.head.appendChild(script);
function getDirections(markers) {
let userLocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(success,error)
function success(position){
userLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
}
}
function error(){
alert("Debes activar la geolocalización")
}
}
//Get directions to nearest marker
jQuery('#FINDPOS').click(() => {
if(typeof(userLocation) === 'undefined'){
alert("Debes permitir la localización")
}
else{
let uLocation = new google.maps.LatLng(userLocation.lat,userLocation.lng)
let distances = [];
let closest = -1;
if(markers.length > 0){
for (i = 0; i < markers.length; i++) {
var d = google.maps.geometry.spherical.computeDistanceBetween(markers[i].position, uLocation.position);
distances[i] = d;
if (closest == -1 || d < distances[closest]) {
closest = i;
}
}
alert('Closest marker is: ' + markers[closest].getTitle());
}
}
})
}
})
Upvotes: 0
Views: 202
Reputation: 161334
Your uLocation
variable is a google.maps.LatLng
object, it doesn't have a .position
property (for that matter, the .position
property of google.maps.Marker
objects isn't documented, it would be safer to call the (documented) .getPosition()
method on the markers
)
var d = google.maps.geometry.spherical.computeDistanceBetween(
markers[i].position, uLocation.position);
should be:
var d = google.maps.geometry.spherical.computeDistanceBetween(
markers[i].getPosition(), uLocation);
related questions:
code snippet:
jQuery(document).ready(function() {
// Create the script tag, set the appropriate attributes
let script = document.createElement('script');
script.src = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=places&libraries=geometry';
script.defer = true;
var map
let infowindow
window.initMap = function() {
const directionsRenderer = new google.maps.DirectionsRenderer();
const center = {
lat: -36.561551,
lng: -72.0954877
}
infowindow = new google.maps.InfoWindow();
map = new google.maps.Map(document.getElementById('map'), {
zoom: 5,
center: center
});
let markers = setMarkers(map)
directionsRenderer.setMap(map);
getDirections(markers, directionsRenderer)
}
const locations = [
['Super Pellet Santiago', -33.458717664930084, -70.77513497336462],
['Super Pellet Chillan', -36.561551, -72.0954877],
['Super Pellet Concepción', -36.8158124, -73.0741686],
['Super Pellet Los Angeles', -37.4774907, -72.3245759],
['Super Pellet Angol', -33.80010128657071, 151.28747820854187],
['Super Pellet Temuco', -38.7702088, -72.6301967]
];
function setMarkers(map) {
let markers = []
for (let i = 0; i < locations.length; i++) {
markers[i] = new google.maps.Marker({
title: locations[i][0],
position: {
lat: locations[i][1],
lng: locations[i][2]
},
map: map
});
google.maps.event.addListener(markers, 'click', (function(markers, i) {
return function() {
infowindow.setContent(locations[i][0]);
infowindow.open(map, markers);
}
})(markers, i));
}
return markers
// Append the 'script' element to 'head'
}
document.head.appendChild(script);
function getDirections(markers, directionsRenderer) {
let userLocation = {
lat: -32.8894587,
lng: -68.8458386
}; // Mendoza, Capital Department, Mendoza Province, Argentina (-32.8894587, -68.8458386)
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(success, error)
function success(position) {
userLocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
}
}
function error() {
document.getElementById('output').innerHTML = "Debes activar la geolocalización<br>defaulting to:Mendoza, Capital Department, Mendoza Province, Argentina (-32.8894587, -68.8458386)";
}
}
//Get directions to nearest marker
jQuery('#FINDPOS').click(() => {
if (userLocation === 'undefined') {
alert("Debes permitir la localización")
} else {
let uLocation = new google.maps.LatLng(userLocation.lat, userLocation.lng);
let distances = [];
let closest = -1;
if (markers.length > 0) {
for (i = 0; i < markers.length; i++) {
var d = google.maps.geometry.spherical.computeDistanceBetween(markers[i].getPosition(), uLocation);
distances[i] = d;
if (closest == -1 || d < distances[closest]) {
closest = i;
}
}
document.getElementById('output').innerHTML = 'Closest marker is: ' + markers[closest].getTitle();
calculateAndDisplayRoute(uLocation, markers[closest].getPosition(), directionsRenderer);
}
}
})
}
})
function calculateAndDisplayRoute(start, end, directionsRenderer) {
const directionsService = new google.maps.DirectionsService();
directionsService.route({
origin: start,
destination: end,
travelMode: google.maps.TravelMode.DRIVING,
},
(response, status) => {
if (status === "OK") {
directionsRenderer.setDirections(response);
} else {
window.alert("Directions request failed due to " + status);
}
}
);
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 90%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<input id="FINDPOS" value="FINDPOS" type="button" />
<div id="output"></div>
<div id="map"></div>
</body>
</html>
Upvotes: 1