2

I would like to dynamically display a popup in leaflet. As you walk towards a point and get within a radius of 10 meters of a point, the popup automatically displays. How to do this?

  • When you say "walk towards a point" do you mean having your mouse near the point? – wfgeo Jan 26 at 10:10
  • No, what I mean is - as you are within a radius of 10m of a point, the popup automatically displays on screen. As you walk to the next point, the previous popup closes and the next one opens. They need to fire without actually clicking on the point. – user1655130 Jan 26 at 14:02
1

This won't be very elegant solution because I have a flu, but that's also the reason I had time to play with it. It wasn't properly tested since I don't have GPS on my laptop, but principles should be clear.

map.locate method is used to fire locationfound event, with parameters that instruct Leafletto continuously watch the location, set view at center of found location and define max zoom that is allowed when view automaticaly set, something like this:

map.locate({setView: true, watch: true, maxZoom: 8});

But in code sequence this comes at the end. There must be event catcher defined for locationfound event, which will deal with displaying and hiding markers:

map.on('locationfound', onLocationFound);

From here on the logic of displaying/hiding near points goes like this:

  • Since there might be very big number of points to check upon, first there is created subset that is within walking distance. Subset is updated if current position changes more than half of walking distance.
  • Then current position is checked against saved near points and if point is no more near, it si removed.
  • Then current postion is checked if it is near any of walking points. If it is, it's then checked if it's already in in array of near points. If not, it's added.

Why didn't I go for geoJSON? Because it doesn't support circles.

So here is the code that I'm sure has errors, but principle should be clear:

var allPoints = [
  [..., ...], 
  [..., ...], 
  ...
];

var walkDistancePoints = [];
var nearDistancePoints = [];
var nearDistanceMarkers = [];
var walkingDistance = 5000;
var nearDistance = 10;
var startWalkDistance;
var firstTime = true;

function getWalkDistancePoints(latlng) {
  walkDistancePoints = [];
  var j = 0;
  for (var i = 0; i < allPoints.length; i++) {
    if (map.distance(latlng, allPoints[i]) <= walkingDistance) {
      walkDistancePoints[j] = allPoints[i];
      j++;
    }
  }
  if (walkDistancePoints.length > 0) {
    startWalkDistance = latlng;
  }
}

function checkForNearPoints(latlng) {
  for (var i = 0; i < nearDistancePoints.length; i++) {
    if (map.distance(latlng, nearDistancePoints[i]) > nearDistance) {
      nearDistanceMarkers.splice(i, 1);
      nearDistancePoints.splice(i, 1);
    }
  }
  for (var i = 0; i < walkDistancePoints.length; i++) {
    if (map.distance(latlng, walkDistancePoints[i]) <= nearDistance) {
      if ((nearDistancePoints.length == 0) || (nearDistancePoints.indexOf(walkDistancePoints[i]) < 0)) {
        nearDistanceMarkers.push(L.marker(walkDistancePoints[i]).addTo(map));
        nearDistancePoints.push(walkDistancePoints[i]);
      }
    }
  }
}

function onLocationFound(e) {
  walkDistancePoints = [];
  if ((walkDistancePoints.length == 0) || (map.distance(e.latlng, startWalkDistance) < (walkingDistance / 2))) {
    getWalkDistancePoints(e.latlng);
  }
  checkForNearPoints(e.latlng);
}
map.on('locationfound', onLocationFound);

map.locate({setView: true, watch: true, maxZoom: 8});      
  • Thanks for your reply on this. Where does it display the marker? Is it possible to fire GeometryUtils.closest and return the closest point and display it perhaps? – user1655130 Feb 1 at 0:31
  • Marker(s) are displayed at points from allPoints array that are within 10 m of current location. You could try GeometryUtils.closest but it would probably be overkill in this case since you just have to iterate over array of points and find those that are within 10 m radius of current position. – TomazicM Feb 1 at 19:52

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.