This is an example of my select by distance using Leaflet

Working Map

I took my Select points within 150 miles code and improved it. I added a panel at the top and put in a HTML select (combobox) to allow the user to pick a distance instead of it being hard coded. I also modified the layer defination to be defined as a null, and then add the GeoJSON data to it. This is more in-line with the ASYNC method and should prevent the map from waiting on a load.

I also added the onEach Feature with an on-lick, so if you click on a feature it will fire off the on-click function and ready the select menu's value and use it to select other points. I left the original map on-click function, you can comment it out if you only want to click on features. No matter if you use the feature or map on-click it will fire off the ProcessClick function and cause the marker and circle to draw. Any points inside will turn green and the output is set to the console as geoJSON.

Some future options would be to put the selected to a table or export out the data as a CSV file or GeoJSON file.

Here is the code.

First I setup the JavaScript libaries, the two Leaflet and the JQuery used for reading the GeoJSON.



<!DOCTYPE html>

<html>
<head><title>Example</title>
	<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />
	<script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet-src.js"></script>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
</head>

Next I'm setting up the CSS code. I'm using the class parent, child-top, child-bottom, so I can have the Map cover the entire page. With out this you have to set the map to a specific height, by using this code I get around page fit problems.

I have the CSS for the Textboxes, I use this ID for the select distance select (combobox).


<style>
html,
body {
	height: 100%;
}

.parent {
	display: flex;
	flex-flow:column;
	height: 100%;  
}

.child-top {
	flex: 0 1 50px;
	background-color: #175B81;
	color:white;
}

.child-bottom {
	flex: 1 1 auto;
}

#txtboxes{
	display:inline-block;
	text-align: right;
	margin: auto;
    width: 95%;
    padding: 10px;
}


</style>

Setting up my div's, The parent has both childs inside it and the child-top has the textbox inside it.

 <div class="parent">
 <div class="child-top" id="panel">
  <div id="txtboxes">

Select on click within 
			<select id="miles">
			  <option value='50'>50 Miles</option>
			  <option value='100' >100 Mile</option>
			  <option value='150'>150 Miles</option>
			  <option value='200'>200 Miles</option>
			  <option value='300'>300 Miles</option>
			  <option value='500'>500 Miles</option>
			</select>
</div>
</div>
<div class="child-bottom" id="map">
</div>

Now the JavaScript, I define a few variables, the map, and the basemap.

<script>

var url = "BaseBallFinal.json";
//Defining variables for the selected points, circle, and click marker
var theMarker;
var theCircle;
var geojsonLayer;

		var map = L.map('map').setView([39.02771, -98.173828], 4);  
   
	var osm=new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',{ 
				attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'}).addTo(map);

Now I define the GeoJSON layer, I called it sites. This is a circleMarker and it has a tooltip which show the Team Name when you mouse over the feature. The layer.on('click') passes the feature coordinates to the ProcessClick function.

Note that it's defined with it's data source as null, then using $.getJSON I grab the data and add it to the layer. Finally I add it ot the map.

		
				
		sites = L.geoJson(null, {
			
			pointToLayer: function(feature, latlng) {
				return L.circleMarker(latlng, {
				radius: 4, //expressed in pixels circle size
				color: "red", 
				stroke: true,
				weight: 7,		//outline width  increased width to look like a filled circle.
				fillOpcaity: 1
				});
				},
				
			onEachFeature: function (feature, layer) {
			
				layer.bindTooltip(feature.properties.Team);

				layer.on('click', function (e) {
					lat = e.latlng.lat;
					lon = e.latlng.lng;
				ProcessClick(lat,lon)	
				});
			}
	
		});

		$.getJSON(url, function(data) {
			sites.addData(data);
		});
		
        sites.addTo(map)

Setting up the layer control and adding it to the map.

		
		//layer control
		var baseMaps = {
			'Open StreetMap':osm
		};
	
		var overlayMaps = {
			"Teams":sites
		};	
		
		L.control.layers(baseMaps, overlayMaps).addTo(map);  
		//END layer control
Now we have the map.on click function. Click anywhere on the map and this is fired off.

Notice it passes the click event coordinates to the same ProcessClick function. This was it does the same thing as when you click on a feature.

If you wanted to restrict the click to the feature, you only need to comment out this map.on function.

		
	// If this map.on "click" function is commented out it will require 
	//you to click on a point feature and it's on-click event to select points.	
  map.on('click',function(e){  
		lat = e.latlng.lat;
		lon = e.latlng.lng;
		ProcessClick(lat,lon)	
  });


ProcessClick First I check to see if "theCircle" exists, if it does it's because I've already clicked somewhere and the on click crerated a marker and a circle, also check for the green GeoJSON points that represent the selected points.

If it exists, remove the circle, the marker, and the points.

Next I add the marker to show where I clicked. I also pass along the coordinate to the SelectPoints function.

function ProcessClick(lat,lon){
	console.log("You clicked the map at LAT: "+ lat+" and LONG: "+lon );
		//Clear existing marker, circle, and selected points if selecting new points
		if (theCircle != undefined) {
		  map.removeLayer(theCircle);
		};
		if (theMarker != undefined) {
			  map.removeLayer(theMarker);
		};
		if (geojsonLayer != undefined) {
			  map.removeLayer(geojsonLayer);
		};
		
	//Add a marker to show where you clicked.
	 theMarker = L.marker([lat,lon]).addTo(map);  //Note: if lat/lon are strings then use parseFloat(lat), parseFloat(lon)
	SelectPoints(lat,lon)

}

The SelectPoints function takes the point as the center point, it reads the select (combobox) value, calculates a radius. Next it checks the distance from the center point and if it's less then the radius, it adds it to an array called selPts.

	
	var selPts = [];

	function SelectPoints(lat,lon){
		var dist = document.getElementById("miles").value;

		xy = [lat,lon];  //center point of circle
		
		var theRadius = parseInt(dist) * 1609.34  //1609.34 meters in a mile //dist is a string so it's convered to an Interger.
		
		selPts.length =0;  //Reset the array if selecting new points
		
		sites.eachLayer(function (layer) {
			// Lat, long of current point as it loops through.
			layer_lat_long = layer.getLatLng();
			
			// Distance from our circle marker To current point in meters
			distance_from_centerPoint = layer_lat_long.distanceTo(xy);
			
			// See if meters is within radius, add the to array
			if (distance_from_centerPoint <= theRadius) {
				 selPts.push(layer.feature);  
			}
		});
	
	

Now I draw the circle knowing the center point and the radius.

	
		// draw circle to see the selection area
		theCircle = L.circle(xy, theRadius , {   /// Number is in Meters
		  color: 'orange',
		  fillOpacity: 0,
		  opacity: 1
		}).addTo(map);

Here I used the selPts as a source for the geojsonLayer. and add them to the map as green circleMarkers.

The points are really JSON not GeoSON, so I process them into GepJSON by putting them into a Feature Collection, and send them to the console.

Finally finishing off the page with HTML tags.

		
		//Symbolize the Selected Points
			 geojsonLayer = L.geoJson(selPts, {
			 
				pointToLayer: function(feature, latlng) {
					return L.circleMarker(latlng, {
					radius: 4, //expressed in pixels circle size
					color: "green", 
					stroke: true,
					weight: 7,		//outline width  increased width to look like a filled circle.
					fillOpcaity: 1
					});
					}
			});
			//Add selected points back into map as green circles.
			map.addLayer(geojsonLayer);
			
			//Take array of features and make a GeoJSON feature collection 
			var GeoJS = { type: "FeatureCollection",  features: selPts   };
			//Show number of selected features.
			console.log(GeoJS.features.length +" Selected features");
			 // show selected GEOJSON data in console
			console.log(JSON.stringify(GeoJS)); 
	}	//end of SelectPoints function

</script>
</body>
</html>