Loading

Web Maps from Scratch

Malcolm Meyer

This is a live streamed presentation. You will automatically follow the presenter and see the slide they're currently on.

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