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

Publishing with GitHub & Jekyll

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!!

<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