A Leaflet-inspired real time map using NYC Open Data. The output continuously updates the previous 7 days' 311 complaints for Grafitti or Dirty Conditions in the borough of the Bronx. The map uses Font Awesome and Maki Markers icons on the Stamen Terrain Background basemap.
Last active
August 29, 2015 14:09
-
-
Save knowaczark/304713a932c7fb476553 to your computer and use it in GitHub Desktop.
Mapping Grafitti and Dirty Conditions in the Bronx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Leaflet - NYC OpenData Example</title> | |
<meta charset="utf-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" /> | |
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.css" rel="stylesheet"> | |
<link rel="stylesheet" href="http://cdn.rawgit.com/lvoogdt/Leaflet.awesome-markers/2.0/develop/dist/leaflet.awesome-markers.css"> | |
<link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300' rel='stylesheet' type='text/css'> | |
<style> | |
html, body { | |
height: 100%; | |
width: 100%; | |
margin: 0; | |
} | |
#map { | |
height: 95%; | |
width: 100%; | |
} | |
#map_title { | |
height: 5%; | |
width: 100%; | |
font: 24px 'Open Sans Condensed', sans-serif; | |
} | |
.leaflet-popup-content { | |
font-family: 'Open Sans Condensed', sans-serif; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="map_title"></div> | |
<div id="map"></div> | |
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> | |
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script> | |
<script src="https://rawgithub.com/leaflet-extras/leaflet-providers/gh-pages/leaflet-providers.js"></script> | |
<script src="http://cdn.rawgit.com/lvoogdt/Leaflet.awesome-markers/2.0/develop/dist/leaflet.awesome-markers.min.js"></script> | |
<script src="http://cdn.rawgit.com/jseppi/Leaflet.MakiMarkers/master/Leaflet.MakiMarkers.js"></script> | |
<script> | |
var zoom = 12; //set zoom level here | |
var center = [40.658528, -73.952551]; //set center coordinates here [latitude, longitude] | |
var map = L.map('map').setView(center, zoom); | |
//declare base map provider | |
//http://leaflet-extras.github.io/leaflet-providers/preview/ | |
//MY NOTE: liked the acetate.terrain with stamen labels | |
var provider_name = "Stamen.TerrainBackground"; //provider name goes here | |
//add provider tile layer to map | |
L.tileLayer.provider(provider_name).addTo(map); | |
map.attributionControl.setPrefix('311 Complaints via NYC OpenData'); //add data source to map's attribute text | |
//data URL variables | |
//set-up dates for complaints placed within past 6 days | |
var start_date = new Date(); | |
start_date.setDate(start_date.getDate()-6); | |
var end_date = new Date(); | |
start_date=f_date(start_date, 'y_mm_dd'); | |
end_date=f_date(end_date, 'y_mm_dd'); | |
//date formatting function Thank You Prof. Culp for the date code | |
function f_date(the_date, d_style){ | |
var dd = ('0' + the_date.getDate()).slice(-2); | |
var mm = ('0' + (the_date.getMonth() + 1)).slice(-2); | |
var y = the_date.getFullYear(); | |
return (d_style == "y_mm_dd")? y + '-' + mm + '-' + dd: mm + '/'+ dd + '/' + y; | |
} | |
var borough = 'Bronx'; | |
var c_type1 = 'Graffiti'; //complaint type 1 | |
var c_type2 = 'Dirty Conditions'; //complaint type 2 | |
$( "#map_title" ).html("Bronx 311 Service Requests for Graffiti and Dirty Conditions from " + start_date + " to " + end_date); | |
//define marker icon using Leaflet Maki Markers | |
//(https://github.com/jseppi/Leaflet.MakiMarkers) | |
var c_type1_icon = L.MakiMarkers.icon({ | |
icon: "art-gallery", //https://www.mapbox.com/maki/ | |
color: "#E363B8", //any hex color (e.g., "#FFFFFF") | |
size: "m", //['s','m','l'] | |
iconSize: [20, 50] | |
}); | |
//define marker icon using Leaflet Awesome | |
//(https://github.com/lvoogdt/Leaflet.awesome-markers) | |
//markerColor options : //['red','darkred','lightred','orange', | |
//'beige','green','darkgreen','lightgreen','blue','darkblue', | |
//'lightblue','purple','darkpurple','pink','cadetblue','white', | |
//'gray','lightgray','black'] | |
//browse icons: http://fortawesome.github.io/Font-Awesome/icons/ | |
var c_type2_icon = L.AwesomeMarkers.icon({ | |
icon: 'trash-o', | |
prefix: 'fa', | |
markerColor: 'orange', | |
iconColor: 'FE8F00' //any hex color (e.g., "#FFFFFF") | |
}); | |
//build the data URL | |
var URL = "http://data.cityofnewyork.us/resource/erm2-nwe9.json"; //API Access Endpoint | |
URL += "?"; //a query parameter name is preceded by the question mark | |
URL += "$where="; //Filters the rows to be returned | |
URL += "(latitude IS NOT NULL)"; //only return records with coordinates | |
URL += " AND "; | |
URL += "(borough='" + borough + "')"; //borough of interest | |
URL += " AND "; | |
URL += "((complaint_type='" + c_type1 + "') OR (complaint_type='" + c_type2 + "'))"; //desired two complaint types nested within parentheses | |
URL += " AND "; | |
URL += "(created_date>='" + start_date + "') AND (created_date<='" + end_date + "')"; //date range | |
URL += "&$group=complaint_type,latitude,longitude"; //fields to group by | |
URL += "&$select=complaint_type,latitude,longitude,count(*)"; //fields to return | |
URL = encodeURI(URL); //encode special characters such as spaces and quotes | |
$.getJSON(URL, function (data) { | |
//console.log(data.length); //the record limit is 1000 so if you get 1000 scale down your date range | |
var c_type1_markers = []; //array to store c_type1 markers | |
var c_type2_markers = []; //array to store c_type2 markers | |
var all_markers = []; //array to store all markers | |
//iterate through records | |
$.each(data, function(index, rec){ | |
//build html string from fields | |
var popup_html = "<b>" + rec.complaint_type + "</b>"; | |
popup_html += "<br>"; | |
popup_html += rec.count + " complaint(s) at this location"; | |
var marker; | |
if (rec.complaint_type==c_type1) { | |
marker = L.marker([rec.latitude, rec.longitude], { icon: c_type1_icon }).bindPopup(popup_html); | |
c_type1_markers.push(marker); //add marker to array of c_type1 markers | |
} | |
else { | |
marker = L.marker([rec.latitude, rec.longitude], { icon: c_type2_icon }).bindPopup(popup_html); | |
c_type2_markers.push(marker); //add marker to array of c_type2 markers | |
} | |
all_markers.push(marker); //add marker to array of all markers | |
}); | |
var all_layer = L.featureGroup(all_markers); //create layer of all markers but do not add to map | |
var c_type1_layer = L.featureGroup(c_type1_markers).addTo(map); //create layer of c_type1 markers and add to map | |
var c_type2_layer = L.featureGroup(c_type2_markers).addTo(map); //create layer of c_type2 markers and add to map | |
map.fitBounds(all_layer.getBounds()); //use layer of all markers to set map extent | |
//create object containing c_type1 and c_type2 marker layers | |
var overlays = {}; | |
overlays[c_type1] = c_type1_layer; | |
overlays[c_type2] = c_type2_layer; | |
//add layer control using above object | |
L.control.layers(null,overlays).addTo(map); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment