This sample demonstrates how to access and chain multiple location services together. It uses the basemap layer, geocoding, routing, and demographics location service.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Esri Leaflet</title>
<!-- Load Leaflet from CDN -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin=""></script>
<!-- Load Esri Leaflet from CDN -->
<script src="https://unpkg.com/esri-leaflet@3.0.14/dist/esri-leaflet.js"></script>
<script src="https://unpkg.com/esri-leaflet-vector@4.2.7/dist/esri-leaflet-vector.js"></script>
<script src="https://unpkg.com/esri-leaflet-geocoder@3.1.4/dist/esri-leaflet-geocoder.js"></script>
<!-- Load Turf from CDN -->
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@5/turf.min.js"></script>
<!-- Load ArcGIS REST JS libraries from https://unpkg.com -->
<script src="https://unpkg.com/@esri/arcgis-rest-request@4/dist/bundled/request.umd.js"></script>
<script src="https://unpkg.com/@esri/arcgis-rest-demographics@4/dist/bundled/demographics.umd.js"></script>
<script src="https://unpkg.com/@esri/arcgis-rest-routing@4/dist/bundled/routing.umd.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: #323232;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const accessToken = "YOUR_ACCESS_TOKEN";
const authentication = arcgisRest.ApiKeyManager.fromKey(accessToken);
const basemapEnum = "arcgis/navigation";
const startcoords = [37.7749, -122.4194];
const zoomLevel = 14;
let getData = false;
const map = L.map("map", {
minZoom: 2
}).setView(startcoords, 6);
const tileLayer = L.esri.Vector.vectorBasemapLayer(basemapEnum, {
token: accessToken
});
tileLayer.addTo(map);
setTimeout(() => {
getData = true;
map.flyTo(startcoords, zoomLevel, {
animate: true,
duration: 3.0
});
}, 1500);
const layerGroup = L.layerGroup().addTo(map);
const layerGroupCoffeeShops = L.layerGroup().addTo(map);
// Add select to go to places
L.Control.PlacesControl = L.Control.extend({
onAdd: function (map) {
// Array of places
const places = [
["Choose a city or click the map", "0.0"],
["San Francisco", "37.7749,-122.4194"],
["New York", "40.7128,-74.0060"],
["London", "51.5074, -0.1278"],
["Sydney", "-33.8688, 151.2093"],
["Toronto", "43.6532, -79.3832"],
["Bangkok", "13.7367,100.5231"]
];
// Create select
const select = L.DomUtil.create("select", "");
select.setAttribute("id", "selectLocation");
select.setAttribute("style", "font-size: 16px; padding: 2px 4px;");
places.forEach(function (place) {
let option = L.DomUtil.create("option");
option.innerHTML = place[0];
option.value = place[1];
select.appendChild(option);
});
L.DomEvent.disableClickPropagation(select);
return select;
},
onRemove: function (map) {
// Nothing to do here
}
});
L.control.placesControl = function (opts) {
return new L.Control.PlacesControl(opts);
};
L.control
.placesControl({
position: "topright"
})
.addTo(map);
document.getElementById("selectLocation").addEventListener("change", goToLocation);
function goToLocation(e) {
getData = true;
const latlngArray = JSON.parse("[" + e.target.value + "]");
var latlng = L.latLng(latlngArray);
map.flyTo(latlng, zoomLevel, {
animate: true,
duration: 2.0
});
}
map.on("moveend", function (e) {
if (getData) {
getDemographicData(e.target.getCenter());
}
getData = false;
});
map.on("click", (e) => {
getDemographicData(e.latlng);
});
function getDemographicData(latlng) {
// Request demographic data for drive time areas
arcgisRest
.queryDemographicData({
studyAreas: [
{
geometry: { x: latlng.lng, y: latlng.lat },
areaType: "NetworkServiceArea",
bufferUnits: "Minutes",
bufferRadii: [2, 5],
travel_mode: "Driving"
}
],
returnGeometry: true,
authentication: authentication
})
.then((response) => {
const data = document.getElementById("data");
if (
response.results[0].value.FeatureSet.length > 0 &&
response.results[0].value.FeatureSet[0].features.length === 2 // Two drive time areas
) {
// Show popup with demographics
const featureSet = response.results[0].value.FeatureSet[0]; //.features[0];
const attributes = featureSet.features[1].attributes;
const content = `<b>Demographics and coffee shops within 2 and 5 minute drive areas</b><br>Population: ${attributes.TOTPOP}<br>Males: ${attributes.TOTMALES} <br>Females: ${attributes.TOTFEMALES}<br>Average Household Size: ${attributes.AVGHHSZ}`;
var popup = L.popup().setLatLng(latlng).setContent(content).openOn(map);
// Display drive time areas
let innerDriveTimeArea = L.esri.Util.arcgisToGeoJSON(featureSet.features[0]);
let outerDriveTimeArea = L.esri.Util.arcgisToGeoJSON(featureSet.features[1]);
displayDrivetimeAreas([innerDriveTimeArea, outerDriveTimeArea]);
// Find coffee shops in drive time area
findPlaces(latlng, outerDriveTimeArea);
} else {
console.log("No data found.");
}
});
function displayDrivetimeAreas(driveTimeAreas) {
layerGroup.clearLayers();
layerGroupCoffeeShops.clearLayers();
driveTimeAreas.forEach((area) => {
L.geoJSON(area, {
style: (feature) => {
const style = {
fillOpacity: 0.5,
weight: 1
};
if (feature.properties.bufferRadii === 0) {
style.color = "hsl(210, 80%, 40%)";
} else if (feature.properties.bufferRadii === 2) {
style.color = "hsl(210, 80%, 60%)";
} else {
style.color = "hsl(210, 80%, 80%)";
}
return style;
}
}).addTo(layerGroup);
});
}
function findPlaces(latlng, serviceAreaPolygon) {
const geocoder = L.esri.Geocoding.geocodeService({
apikey: accessToken
});
geocoder
.geocode()
.category("Coffee shop")
.nearby(latlng, 50)
.run(function (error, response) {
if (error) {
return;
}
const intersectedFeatures = response.results.filter((feature) => {
return turf.booleanPointInPolygon([feature.latlng.lng, feature.latlng.lat], serviceAreaPolygon);
});
intersectedFeatures.forEach((searchResult) => {
L.marker(searchResult.latlng)
.addTo(layerGroupCoffeeShops)
.bindPopup(`<b>${searchResult.properties.PlaceName}</b></br>${searchResult.properties.Place_addr}`);
});
});
}
}
</script>
</body>
</html>