Building Web Apps with the
Esri-Leaflet Plugin
Aaron Parecki @aaronpk
CTO, Esri R&D Center Portland
Esri-Leaflet
ArcGIS Services Plug-in
Leaflet
 Open
 Pure

source mapping library

JavaScript – 31kb

 Simple,
 Many

easy to use, mobile friendly

plug-ins

www.leafletjs.com
Leaflet Features
What’s there?

What’s missing?

 Draw

 Basemaps

 Add

pop-ups

 Read
 Add

map tiles
GeoJSON

graphics

 Symbolize
 Control
 Add

features

layers

other controls

 Plugins…

 ArcGIS

support
 Basemaps
 Feature Services
 Other Services


Widgets
 Webmaps
 Cloud

storage
Esri-Leaflet
ArcGIS Online Services Plug-in

 Open

source plug-in for ArcGIS Online services

 Extends
 Built

L.class and namespace

with Terraformer - GeoJSON

http://esri.github.io/esri-leaflet/
Esri-Leaflet: Getting Started
L.esri.xxx
<!DOCTYPE html>
<html>
<head>
<title>Esri Leaflet</title>
<link rel="stylesheet" href="/the/path/to/leaflet.css" />
<style>
html, body, #map { width: 100%; height: 100%; }
</style>
<script src="/the/path/to/leaflet.js"></script>
<script src="/the/path/to/esri-leaflet.min.js"></script>
</head>
<body>
<div id="map"></div>
<script>
var map = L.map('map');
L.esri.basemapLayer("Streets").addTo(map);
map.setView([38.97993, -104.9794], 12);
</script>
</body>
</html>
Esri-Leaflet: ArcGIS Basemaps
http://esri.github.io/esri-leaflet/arcgisbasemaps.html

L.esri.BasemapLayer = L.TileLayer.extend({…
// Load an ArcGIS basemap
var map = L.map('map').setView([37.75,-122.45], 12);
L.esri.basemapLayer("Topographic").addTo(map);
// Supported basemap types
//L.esri.basemapLayer("Streets").addTo(map);
//L.esri.basemapLayer("Oceans").addTo(map);
//L.esri.basemapLayer("NationalGeographic").addTo(map);
//L.esri.basemapLayer("Gray").addTo(map);
//L.esri.basemapLayer("GrayLabels").addTo(map);
//L.esri.basemapLayer("Imagery").addTo(map);
//L.esri.basemapLayer("ImageryLabels").addTo(map);
Esri-Leaflet: ArcGIS FeatureServices
http://esri.github.io/esri-leaflet/arcgisfeatureservice.html

L.esri.FeatureLayer = L.GeoJSON.extend({…
// Access ArcGIS FeatureService
var map = L.map('map').setView([45.52963623111275, -122.67389774322508],
12);
L.esri.basemapLayer("Topographic").addTo(map);
var url =
'http://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/stops/Feature
Server/0’
L.esri.featureLayer(url);
Esri-Leaflet: Symbols
http://esri.github.io/esri-leaflet/symbolizepointfeatures.html
// Create FeatureLayer and define styles
L.esri.featureLayer(url, {
style: function (feature) {
return getStyle(feature);
}).addTo(map);
function getStyle(feature) {
var c,o = 0.5;
switch (feature.properties.BIKEMODE) {
case "Low traffic through street":
c = "#007D7D";
break;
case "Bike boulevard":
c = "#00FF3C";
break;
…
}
return {color: c, opacity: o};
}
Esri-Leaflet: Popups
// Create FeatureLayer and bind to popup
L.esri.featureLayer(featureServiceUrl, {
onEachFeature: createPopup
}).addTo(map);
// Define popup content - show all fields and values
function createPopup(geojson,layer) {
if (geojson.properties) {
var popupText = "<div style='max-height:200px;'>";
for (prop in geojson.properties) {
var val = geojson.properties[prop];
if (val) {
popupText += "<b>" + prop + "</b>: " + val + "<br>";
}
}
popupText += "</div>";
layer.bindPopup(popupText);
}
}
Esri-Leaflet: DynamicMapLayer
http://esri.github.io/esri-leaflet/dynamicmapservice.html
// ArcGIS Server Dynamic Map Service - Hurricane Tracks
dynLayer =
L.esri.dynamicMapLayer("http://tmservices1.esri.com/arcgis/rest/services/LiveFeeds/H
urricane_Recent/MapServer", { layers:[0,1] });
// Identifying Dynamic Map Service Features
map.on("click", function(e) {
dynLayer.identify(e.latlng, {
layerDefs: {
0: "STORMNAME='ANDREA'",
1: "STORMNAME='ANDREA'"
}
}, function(data) {
popupText = "<center><b>" +
data.results[0].attributes.STORMNAME + "</b><br>" +
data.results[0].attributes.STORMTYPE + "</center>”;
L.popup().setLatLng(e.latlng).setContent
(popupText).openOn(map);
}
});
});
Esri-Leaflet: ClusterFeatureLayer
http://esri.github.io/esri-leaflet/basicclustering.html
// Reference cluster plug-in and esri feature layer
<script src="lib/markercluster/leaflet.markercluster.js"></script>
<script src="lib/esri-leaflet/extras/clustered-feature-layer.js"></script>
// Create and add a new feature cluster layer
var fl =
L.esri.clusteredFeatureLayer("http://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/
services/stops/FeatureServer/0", {
cluster: new L.MarkerClusterGroup(),
onEachMarker: function(geojson, marker) {
marker.bindPopup("<h3>"+
geojson.properties.stop_name+"</h3><p>
Stop ID: "+geojson.properties.stop_id+"</p><p>”
+geojson.properties.stop_desc+"</p>")
}
}).addTo(map);
Esri-Leaflet: FeatureService Query
http://esri.github.io/esri-leaflet/featureservicequery.html
// Access feature service directly and query (geoservices.js)
var fs = new GeoServices.FeatureService({url:featureServiceUrl}, function (err, results)
{
var queryOptions = document.getElementById("query");
var query = queryOptions.text;
var queryEnvelope =
JSON.stringify(L.esri.Util.boundsToExtent(map.getBounds()));
// Build query parameters
var params = {
f:"json”, where: query,
geometry: queryEnvelope,
spatialRel: "esriSpatialRelIntersects”,
returnGeometry:true, outSR: 4326, outFields:"*"
};
// Query the feature service
fs.query(params, function (err, results) {
addFeaturesToMap(results);
}
}
Esri-Leaflet: Geocoding
http://esri.github.io/esri-leaflet/findplaces.html
// Reference geoservices.js
<script src="lib/geoservices/geoservices.js"></script>
…
var GeoServices = new Geoservices.Geoservices({});
var options = {
text:searchString,
outFields: "Loc_name,Place_addr",
bbox: mapBounds }
// Add geocodes to map
GeoServices.geocode(options, function (err,result) {
for (var i = 0; i < result.locations.length; i++) {
var place = result.locations[i];
var pt = new L.LatLng(place.feature.geometry.y, place.feature.geometry.x);
var marker = L.marker(pt).bindPopup(place.name + "</br>" +
place.feature.attributes.Place_addr);
layerPlaces.addLayer(marker);
}
}
Esri-Leaflet: Directions
http://esri.github.io/esri-leaflet/directions.html

 Directions
 Use

service requires an access token

OAuth 2.0 to log users in without obtaining
their password
Licensing
 Free ArcGIS

Developer Subscription

 Testing

and development
 Public deployments (non-commercial)
 50 credits
 Paid ArcGIS

Developer or ArcGIS Organization

Subscription
 Private

deployments
 Commercial deployments (generates revenue)
esri.github.com

Building Web Apps with the Esri-Leaflet Plugin - Dubai DevSummit 2013

Editor's Notes

  • #2 Esri Corporate Template V2September 6, 2013See http://arczone/resources/presentations.cfm for more sample files and help.
  • #8 ----- Meeting Notes (11/20/13 10:52) -----show example of using custom tile services