Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Using ESRI JSON in Leaflet

Basic example of taking an output from our server and putting it on a map. As leaflet allows you to add geoJSON directly, we convert it from esri's JSON format to a more standard one.

<!doctype html>
<html lang="en">
<head>
<meta charset='utf-8'/>
<style>
html { height: 100% }
body { height: 100%; margin: 0; padding: 0;}
#map{ height: 100% }
</style>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.3.1/leaflet.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.3.1/leaflet.ie.css" />
<![endif]-->
<script src="http://cdn.leafletjs.com/leaflet-0.3.1/leaflet.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<title>
Cameras
</title>
</head>
<body>
<div id="map"></div>
<script type="text/javascript" src="toGeoJSON.js"></script>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
//set the options
var center = new L.LatLng(42.3584308,-71.0597732);
var zoom = 8;
var url= "http://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png";
var options={
subdomains:["otile1","otile2",/*"otile3",*/"otile4"],//we'd usually use all 4 but something is up with #3 at the moment
attribution:"Tiles Courtesy of <a href='http://www.mapquest.com/' target='_blank'>MapQuest</a> <img src='http://developer.mapquest.com/content/osm/mq_logo.png'>"
};
//create the tiles
var tiles = new L.TileLayer(url,options);
//create the map
var m = new L.Map('map',{
center:center,
zoom:zoom,
layers:[tiles]
});
var gj = new L.GeoJSON();
//create empty geojson object and add it to the map
m.addLayer(gj);
//create the popups
gj.on("featureparse", function (e) {
if (e.properties){
e.layer.bindPopup(makePop(e.properties));
}
});
//get the current bounds
var bbox=m.getBounds().toBBoxString();
//the url
var url = "http://services.massdot.state.ma.us/ArcGIS/rest/services/Assets/SmartCameras/MapServer/0/query?outFields=*&f=json&outSR=4326&inSR=4326&geometryType=esriGeometryEnvelope&geometry="
//get the features
$.get(url+bbox,parseJSONP,"JSONP");
//this is the call back from the jsonp ajax request
function parseJSONP(data){
//we call the function to turn it into geoJSON and write a callback to add it to the geojson object
toGeoJSON(data,
function(d){
gj.addGeoJSON(d)
}
);
}
//the function called earlier to make the popup, it goes through all the attributes and makes them into a nice key value list
function makePop(p){
var a = [];
for(var key in p){
a.push(key+": "+p[key]);
}
return a.join("<br/>");
};
/*
fork me on github: http://github.com/calvinmetcalf/esri2geo
*/
function toGeoJSON(data,cb){
var outPut = { "type": "FeatureCollection",
"features": []};
var fl = data.features.length;
var i = 0;
while(fl>i){
var ft = data.features[i];
/* as only ESRI based products care if all the features are the same type of geometry, check for geometry type at a feature level*/
var outFT = {
"type": "Feature",
"properties":ft.attributes
};
if(ft.geometry.x){
//check if it's a point
outFT.geometry=point(ft.geometry);
}else if(ft.geometry.points){
//check if it is a multipoint
outFT.geometry=points(ft.geometry);
}else if(ft.geometry.paths){
//check if a line (or "ARC" in ESRI terms)
outFT.geometry=line(ft.geometry);
}else if(ft.geometry.rings){
//check if a poly.
outFT.geometry=poly(ft.geometry);
}
outPut.features.push(outFT);
i++;
}
function point(geometry){
//this one is easy
return {"type": "Point","coordinates": [geometry.x,geometry.y]};
}
function points(geometry){
//checks if the multipoint only has one point, if so exports as point instead
if(geometry.points.length===1){
return {"type": "Point","coordinates": geometry.points[0]};
}else{
return { "type": "MultiPoint","coordinates":geometry.points};
}
}
function line(geometry){
//checks if their are multiple paths or just one
if(geometry.paths.length===1){
return {"type": "LineString","coordinates": geometry.paths[0]};
}else{
return { "type": "MultiLineString","coordinates":geometry.paths};
}
}
function poly(geometry){
//first we check for some easy cases, like if their is only one ring
if(geometry.rings.length===1){
return {"type": "Polygon","coordinates": geometry.rings};
}else{
/*if it isn't that easy then we have to start checking ring direction, basically the ring goes clockwise its part of the polygon, if it goes counterclockwise it is a hole in the polygon, but geojson does it by haveing an array with the first element be the polygons and the next elements being holes in it*/
var ccc= dP(geometry.rings);
var d = ccc[0];
var dd = ccc[1];
var r=[];
if(dd.length===0){
/*if their are no holes we don't need to worry about this, but do need to stuck each ring inside its own array*/
var l2 = d.length;
var i3 = 0;
while(l2>i3){
r.push([d[i3]]);
}
return { "type": "MultiPolygon","coordinates":r};
}else if(d.length===1){
/*if their is only one clockwise ring then we know all holes are in that poly*/
dd.unshift(d[0]);
return {"type": "Polygon","coordinates": dd};
}else{
/*if their are multiple rings and holes we have no way of knowing which belong to which without looking at it specially, so just dump the coordinates and add a hole field, this may cause errors*/
return { "type": "MultiPolygon","coordinates":d, "holes":dd};
}
}
}
function dP(a){
//returns an array of 2 arrays, the first being all the clockwise ones, the second counter clockwise
var d = [];
var dd =[];
var l = a.length;
var ii = 0;
while(l>ii){
if(c(a[ii])){
d.push(a[ii]);
}else{
dd.push(a[ii]);
}
ii++;
}
return [d,dd];
}
function c(a){
//return true if clockwise
var l = a.length-1;
var i = 0;
var o=0;
while(l>i){
o+=(a[i][0]*a[i+1][1]-a[i+1][0]*a[i][1]);
i++;
}
return o<=0;
}
if(cb){
cb(outPut)
}else{
return outPut;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment