Reputation: 141
I want to make a div appear based on distance. For this I'm getting the location of the user and the coordinates of the place the div is supposed to appear and I'm being successful making this happen. My problem now, is that there's gonna be different places where I want this to be available, so I need to find a way to loop and constantly be checking where the person is and see if its close to the distance of my coordinates.
-- Getting Location of person
if (navigator.geolocation){
navigator.geolocation.watchPosition(showPosition)
}
-- Function to work div appearing
function showPosition(position){
let locationLatitude = []
let locationsLongitude = []
//AJAX CALL TO GET THE POSITION OF THE PLACES AND PUSHING THEM TO THE ARRAYS
let success = function(res){
let locations = res.locations
for (var i=0; i<locations.length; i++){
locationLatitude.push(locations[i]['place_latitude'])
locationsLongitude.push(locations[i]['place_longitude'])
}
}
$.ajax({
type: 'GET',
url: '/api/locations',
crossDomain: true,
dataType: 'json',
async: false,
success : success,
});
// LOOP TO GET ALL COORDIANTES FROM PLACES (LAT,LONG)
var locationLatitudeLength = locationLatitude.length
var locationsLongitudeLength = locationsLongitude.length
let startPosLat
let startPosLong
for(var i=0; i<locationLatitudeLength; i++){
for(var j=0; j<locationsLongitudeLength; j++){
startPosLat = locationLatitude[i]
startPosLong = locationsLongitude[j]
userlocationLatitude = position.coords.latitude
userlocationLongitude = position.coords.longitude
//PASS VALUES OF COORDINATES TO THE FUNCTION
let distance = calculateDistance(startPosLat, startPosLong, userlocationLatitude, userlocationLongitude)
}
}
if(distance < .05){
$('.div-image').attr('src', 'pic2.jpg')
}else if(distance > .05){
$('.div-image').attr('src', 'pic.jpg')
}
//function to calculate the distance between two points of coordinates
function calculateDistance(lat1, lon1, lat2, lon2) {
var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
}
the problem with this is that it doesn't recognize the coordinates coming from the loop.
Anyone has a recommendation on how to make the function run for each coordinate on the loop to check if I'm there or not.
Upvotes: 1
Views: 466
Reputation: 4246
I think your algorithm could be simplified quite a bit. In particular, breaking the latitudes and longitudes into separate arrays and then later using nested for
loops to reunite them seems unnecessary. Here's a suggestion that skips those steps.
Note that this is totally untested, but it might get you well along the right track.
Other things to note are the possibility of using for...of
instead of traditional for
loops, using distance
in the same scope in which it gets declared, and being ready for the situation where distance == .05
.
function showPosition(position){
const userlocationLatitude = position.coords.latitude;
const userlocationLongitude = position.coords.longitude;
let success = function(res){
for(let location of res.locations){
let startPosLat = location['place_latitude'],
startPosLng = location['place_longitude'],
distance = calculateDistance(startPosLat, startPosLong, userlocationLatitude, userlocationLongitude);
if(distance < .05){ $('.div-image').attr('src', 'pic2.jpg'); }
else{ $('.div-image').attr('src', 'pic.jpg'); }
}
}
$.ajax({ type: 'GET', url: '/api/locations', crossDomain: true, dataType: 'json', async: false, success : success });
//function to calculate the distance between two points of coordinates
function calculateDistance(lat1, lon1, lat2, lon2) {
var R = 6371, dLat = (lat2-lat1).toRad(), dLon = (lon2-lon1).toRad(),
a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * Math.sin(dLon/2) * Math.sin(dLon/2),
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
Number.prototype.toRad = function() { return this * Math.PI / 180; }
}
Upvotes: 1
Reputation: 305
It appears that the double loop going through the coordinates does not wait for the response from the ajax (I'm assuming that all of the coordinates are required before processing). Since the ajax call is asynchronous, the locations won't be populated until the server responds; however, the loop going through the locations array will start executing immediately after the initial request is made to the server and, most importantly, before the locations are populated.
Try moving a majority of your function into the success function.
function showPosition(position){
let locationLatitude = []
let locationsLongitude = []
//AJAX CALL TO GET THE POSITION OF THE PLACES AND PUSHING THEM TO THE ARRAYS
let success = function(res){
let locations = res.locations
for (var i=0; i<locations.length; i++){
locationLatitude.push(locations[i]['place_latitude'])
locationsLongitude.push(locations[i]['place_longitude'])
}
// LOOP TO GET ALL COORDIANTES FROM PLACES (LAT,LONG)
var locationLatitudeLength = locationLatitude.length
var locationsLongitudeLength = locationsLongitude.length
let startPosLat
let startPosLong
for(var i=0; i<locationLatitudeLength; i++){
for(var j=0; j<locationsLongitudeLength; j++){
startPosLat = locationLatitude[i]
startPosLong = locationsLongitude[j]
userlocationLatitude = position.coords.latitude
userlocationLongitude = position.coords.longitude
//PASS VALUES OF COORDINATES TO THE FUNCTION
let distance = calculateDistance(startPosLat, startPosLong, userlocationLatitude, userlocationLongitude)
}
}
if(distance < .05){
$('.div-image').attr('src', 'pic2.jpg')
}else if(distance > .05){
$('.div-image').attr('src', 'pic.jpg')
}
}
$.ajax({
type: 'GET',
url: '/api/locations',
crossDomain: true,
dataType: 'json',
async: false,
success : success,
});
//function to calculate the distance between two points of coordinates
function calculateDistance(lat1, lon1, lat2, lon2) {
var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
}```
Upvotes: 3
Reputation: 1892
I would first suggest using an array of arrays to store coordinates so your latitude and longitude are referenced near eachother. I have given some basic examples of looping, assuming checkFunction is something you define to handle the coordinate checks.
You can use vanilla JS to loop like this:
for (var i in myArray) {
checkFunction(myArray[i]);
}
Or you can use JQuery to loop like this:
$(myArray).each(function(index, value) {
checkFunction(value);
});
Upvotes: 1