index.js
function getParks() {
return new Promise(function(resolve, reject) {
let parks = L.esri.query({
url:
"https://services7.arcgis.com/ocKjSej9kmTKCjNK/arcgis/rest/services/AccessPoints_LOS_20180301_FIRST/FeatureServer/0"
});
parks.run(function(err, response, raw) {
if (err) return reject(err);
resolve(response);
});
});
}
function twoDecimal(val) {
return numeral(val).format("0.00");
}
async function main() {
let routesLayer = L.featureGroup();
let selectionLayer = L.featureGroup();
let searchBuffer = L.featureGroup();
let searchLayer = L.featureGroup();
let pulsingIcon = L.icon.pulse({
iconSize: [8, 8],
color: "#18FFFF",
fillColor: "#18FFFF",
animate: true,
heartbeat: 2
});
let endLayer = L.featureGroup();
let map = L.map("map").setView([35.77959, -78.638179], 13);
L.esri.basemapLayer("DarkGray").addTo(map);
map.addLayer(routesLayer);
map.addLayer(selectionLayer);
map.addLayer(searchLayer);
map.addLayer(endLayer);
var parks = await getParks();
var parksLayer = L.geoJson(parks, {
pointToLayer: function(geojson, latlng) {
return L.circleMarker(latlng, {
color: "#fff",
weight: 0.25,
fillColor: "#18FFFF",
fillOpacity: 0.4,
radius: 4
});
}
}).addTo(map);
let closestFacilityService = L.esri.GP.service({
url:
"https://utility.arcgis.com/usrsvcs/appservices/FnVYYTap8ykTDC1m/rest/services/World/ClosestFacility/NAServer/ClosestFacility_World",
path: "solveClosestFacility"
});
let closestFacilityTask = closestFacilityService.createTask();
closestFacilityTask.setParam("returnCFRoutes", true);
map.on("click", function(evt) {
routesLayer.clearLayers();
selectionLayer.clearLayers();
searchBuffer.clearLayers();
searchLayer.clearLayers();
endLayer.clearLayers();
var infoListItems = document
.getElementById("info-list")
.getElementsByTagName("li");
console.log(infoListItems);
for (var i = 0; i < infoListItems.length - 1; i++) {
infoListItems[i].textContent = "";
}
L.esri.Geocoding.reverseGeocode()
.latlng(evt.latlng)
.run(function(err, result, raw) {
console.log(raw);
document.getElementById("info-box-start").textContent =
"Start Location: " + raw.address.ShortLabel;
});
let lngLat = turf.point([evt.latlng.lng, evt.latlng.lat]);
searchBufferResult = turf.buffer(lngLat, 1.29, { units: "miles" });
searchBuffer = L.geoJson(searchBufferResult, {
style: {
color: "#fff",
fillOpacity: 0,
lineCap: "mitre",
dashArray: "20, 10",
weight: 8
}
});
searchBuffer.addTo(map);
map.flyToBounds(searchBuffer.getBounds());
let parksFeatures = parks.features;
let parksCollection = [];
for (i = 0; i < parksFeatures.length; i++) {
var coordinates = parksFeatures[i].geometry.coordinates;
parksCollection.push(coordinates);
}
var searchLayerResult = turf.pointsWithinPolygon(
turf.points(parksCollection),
turf.polygon(searchBufferResult.geometry.coordinates)
);
if (searchLayerResult.features.length > 0) {
searchLayer = L.geoJson(searchLayerResult, {
pointToLayer: function(geojson, latlng) {
return L.circleMarker(latlng, {
weight: 0,
fillOpacity: 0,
radius: 0
});
}
});
searchLayer.addTo(map);
selectionLayer.addLayer(
L.shapeMarkers.crossMarker(evt.latlng, 15, {
color: "white",
weight: 4
})
);
closestFacilityTask.setParam("incidents", evt.latlng);
closestFacilityTask.setParam("facilities", searchLayerResult);
closestFacilityTask.setParam(
"restrictionAttributeNames",
"Preferred for Pedestrians"
);
closestFacilityTask.run(function(err, res, raw) {
console.log(err);
var routesFeature = res.routes.features[0];
routesLayer.addLayer(
L.geoJSON(routesFeature, {
style: {
color: "#FFFF00",
weight: 2,
opacity: 1
}
})
);
var routesFeatureArray = routesFeature.features;
console.log(routesFeatureArray);
var turfRouteLength = turf.length(routesFeature, { units: "miles" });
var esriRouteLength = routesFeature.properties.Total_Miles;
document.getElementById("info-box-ndist").textContent =
"Route Distance: " + twoDecimal(esriRouteLength) + " mi";
var end =
routesFeature.geometry.coordinates[
routesFeature.geometry.coordinates.length - 1
];
var endBuffer = turf.buffer(turf.point(end), 0.05, { units: "miles" });
var endPoint = turf.pointsWithinPolygon(parks, endBuffer);
document.getElementById("info-box-park").textContent =
"Park: " + endPoint.features[0].properties.PARK_NAME;
var euclidDist = turf.distance(
turf.point([evt.latlng.lng, evt.latlng.lat]),
turf.point(end),
{ units: "miles" }
);
document.getElementById("info-box-edist").textContent =
"Euclidean Distance: " + twoDecimal(euclidDist) + " mi";
var distRatio = esriRouteLength / euclidDist;
document.getElementById("info-box-ratio").textContent =
"Circuity Ratio: " + twoDecimal(distRatio) + ":1";
endLayer.addLayer(
L.marker(end.reverse(), {
icon: pulsingIcon
})
);
});
} else {
document.getElementById("info-box-park").innerHTML =
"<i>No parks in search area</i>";
}
});
}
main();
style.css
@import url('https://fonts.googleapis.com/css?family=Oswald|Roboto');
html, body {
margin: 0;
padding: 0;
font-family: 'Oswald', sans-serif;
}
#map {
position:absolute;
top: 0;
bottom: 0;
width: 100%;
}
#info-pane {
position: absolute;
top: 10px;
right: 10px;
z-index: 1000;
padding: 1em;
background: white;
max-width: 240px;
}
#info-box {
color: white;
position: absolute;
top: 0;
right: 0;
padding: 10px 10px 0 0;
max-width: 33%;
z-index: 1000;
}
#info-box h1 {
margin: 0;
font-size: 4em;
text-shadow: rgb(0, 0, 0) 0px 0px 20px,
rgb(0, 0, 0) 10px 10px 40px;
}
#info-box ul {
margin: 4px 0;
list-style-type: none;
font-size: 1.4em;
text-shadow: rgb(0, 0, 0) 0px 0px 6px,
rgb(0, 0, 0) 4px 4px 12px;
}
#info-box-hover {
font-style: italic;
}
@media (max-width: 900px) {
#info-box h1 {
font-size: 3em;
}
#info-box p {
font-size: 1.2em;
}
}
@media (max-width: 600px) {
#info-box h1 {
font-size: 2em;
}
#info-box p {
font-size: 1em;
}
}
@media (max-width: 400px) {
#info-box h1 {
font-size: 1.8em;
}
}
@media (max-width: 300px) {
#info-box h1 {
font-size: 1.2em;
}
#info-box p {
font-size: 0.8em;
}
}