Web Maps from Scratch
Ohio URISA GIS Education Series 2017 Workshop
"An Introduction to Leaflet, GitHub & Jekyll"
Malcolm Meyer, OVRDC
Jesse Glascock, Pirme 3SG
Jon Woyame, Prime 3SG
Outline
Leaflet JS
-
Considerations for Web Maps
-
Live Examples
-
Make a Map! - ovrdc.github.io/gis-tutorials
- Mapbox GL Choropleth Example
Publishing with GitHub & Jekyll
-
Jekyll Intro (Video)
-
Map Templates
-
Example based on Google's Dashboard Template
What is Leaflet?
JavaScript web mapping API created in 2011 by Vladimir Agafonkin of Cloudmade (now with Mapbox).
Leaflet 1.0.3 was released in January 2017
Open Source
Small & Simple
Hundreds of Plugins
Large Online Community
Prime 3SG Examples
Commerce City plow tracker https://snowtrooper.c3gov.com/
Franklin County election results
http://vote.franklincountyohio.gov/elections
Middlesex County demographics
http://gis.prime3sg.com/middlesex/demographics2
Facebook Live Example
HTML, CSS & JavaScript
Considerations
Solutions
No GUI
Limitations for Rendered Data (GeoJSON, TopoJSON, etc)
Layer Indexing, Layering & Layer Control Limitations
Limitations
Develop Templates Jekyll/Node JS
Expand Internal Knowledge
Focus Web Apps or use Hosted Data (Esri, Mapbox, CARTO)
Use a Plugin or use a Custom Layer Control
JavaScript
Programming Language for the Web and Beyond
What JavaScript looks like
<--
{ "type": "FeatureCollection",
"features": [
{ "type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
[100.0, 1.0], [100.0, 0.0] ]
]
},
"properties": {
"prop0": "value0",
"prop1": {"this": "that"}
}
}
]
}
GeoJSON & TopoJSON
Let's Make a MAP!!
- ovrdc.github.io/gis-tutorials
- GIS Tutorials Zip File with Jekyll Layout
- leaflet-blank.html
Fullscreen Blank HTML Map Template - leaflet-full-example.html
HTML Page with all Examples - Leaflet JS & Plugins
- Data (GeoJSON)
- Jekyll Layout based on Bulma Projects
- leaflet-blank.html
<html>
<head>
<title>Leaflet Map Intro</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Leaflet -->
<link rel="stylesheet" href="_leaflet/plugins/leaflet/leaflet.css" />
<script src="_leaflet/plugins/leaflet/leaflet.js"></script>
<!-- Plugins -->
<style>
body,html {height:100%;width:100%;margin:0;}
#map {width:100%;height:100%;background:whitesmoke;}
</style>
</head>
<body>
<div id="map"></div>
<script>
/*Our Leaflet Map Here*/
</script>
</body>
</html>
Fullscreen Map
var map = L.map("map");
map.setView([40.3,-96.6], 5);
L.hash(map); //plugin
L.control.scale().addTo(map); //built-in function
//built-in function
var layerControl = L.control.layers().addTo(map);
Basic Leaflet Map
Text
Basic Leaflet Map
Text
/*Easily add basemaps or baselayers with L.tileLayer
WMS layers can also be added with L.tileLayer.wms */
var tileUrl = 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png';
var attribution = '© OpenStreetMap, Tiles courtesy of Humanitarian OpenStreetMap Team';
var OpenStreetMap_HOT = L.tileLayer(tileUrl, {
maxZoom: 19,
attribution: attribution
}).addTo(map);
layerControl.addBaseLayer(OpenStreetMap_HOT, "Streets");
Adding Tile Layers (Basemaps)
Adding Tile Layers (Basemaps)
// Load data with leaflet-omnivore, then add it to
// our empty counties layer
var url = "tutorial-data/counties.topojson";
var counties = L.geoJson().addTo(map);
layerControl.addOverlay(counties, "Counties");
var cData = omnivore.topojson(url, null, counties);
Add Data Layers
Add Data Layers
var counties = L.geoJson(null, {
style: function(feature) {
switch(feature.properties.winner) {
case "Trump": return {fillColor: "red"}
default : return {fillColor: "blue"}
}
},
onEachFeature: function(feature, county) {
var info = county.feature.properties.NAME +
"<br>" + county.feature.properties.winner;
county.bindPopup(info);
}
});
Styling & Interaction
Styling & Interaction
var url2= "tutorial-data/airports.geojson"
var aStyle= {
color: "black",
radius: 5,
weight: 0,
fillOpacity: 1,
pane: "markerPane" };
var airports = L.geoJson(null, {
pointToLayer: function(feature, latlng) {
return L.circleMarker(latlng, aStyle)
}
}).addTo(map);
var aData= omnivore.geojson(url2, null, airports);
Styling Points
Styling Points
Leaflet Plugins
// Once our county data is loaded,
// add search functionality using
// leaflet-search with default settings
cData.on("ready", function() {
var searchControl = new L.Control.Search({
layer: counties,
propertyName: 'NAME'
}).addTo(map);
});
Searching Layers
Searching Layers
var choropleth;
cData.on("ready", function() {
choropleth = L.choropleth(cData.toGeoJSON(), {
valueProperty: "POP_SQMI",
scale: ["white","#006d2c"],
steps: 7,
mode: "q",
style: {color: "#fff",weight: 1,fillOpacity: 0.9},
onEachFeature: function(feature, county) {
var name = feature.properties.NAME;
county.bindTooltip(name);
}
}).addTo(map);
});
Choropleth
Choropleth
*legend code not shown in previous page
var airportJson;
aData.on('ready', function() {
aData.toGeoJSON();
airportJson = aData.toGeoJSON();
});
var highlightStyle = {
color: "goldenrod",
fillColor: "goldenrod",
opacity: 1,
fillOpacity: 1,
pane: "markerPane"
}
var highlight = new L.geoJson(null, {
pointToLayer: function(feature, latlng) {
return new L.circleMarker(latlng, highlightStyle)
}
}).addTo(map);
counties.on("mouseover", function(e) {
highlight.clearLayers();
var selLayer = new L.geoJson(e.layer.toGeoJSON());
var within = turf.within(airportJson, selLayer.toGeoJSON());
highlight.addData(within);
});
Turf GIS Analysis
Turf GIS Analysis
hovering over a county highlights the points inside that county
Part II
Building a Web Map Publishing Platform with GitHub & Jekyll
GitHub is a code hosting platform for version control and collaboration. It offers free web hosting for small projects and has built-in support for Jekyll and GeoJSON.
Jekyll is a "simple, blog aware, static site generator", based on Ruby, with Markdown support. Jekyll uses the Liquid templating language and yaml for config files.
How and Why use GitHub & Jekyll?
- Page Templates
- Code Backup
- Simple Hosting
- No Databases to Manage
- Static Sites are AWESOME!
- Example
GitHub Web Publishing
Benefits
Free Hosting!!
Raw HTML, CSS & JavaScript
Jekyll Sites
Built-In Themes
Third-Party Integration
Editable by Multiple Users
Limits
Limited Size & Capacity on Free Accounts
Free Repositories are Public
Choosing & Building the Map Template
Mobile
First
Design
Is This the Best We Can Do?
Why Reinvent the Wheel?
Templates from Esri & Google
Material Maps
- Simple Structure
- One Map Layout
- Gallery Layout
- Maps are a Jekyll 'Collection'
- Similar template in use at OVRDC
Material Maps Live
THANKS!!
Malcolm Meyer
mmeyer@ovrdc.org
Jesse Glascock
jglascock@prime3sg.com
Jon Woyame
jwoyame@prime3sg.com