Free and Open Source Geospatial Tools for Conservation Planning Workshop - FOSS4G 2018 - Dar Es Salaam
Step by step documentation for developing a small web application that allows users to show, query and interact with geospatial data.
Demo: https://lucageo.github.io/foss4g2web/
Go to:
cd /usr/local/lib/geoserver-2.10.4/webapps/geoserver/WEB-INF
Open with VIM the following file:
sudo vim web.xml
Uncomment the following lines:
<context-param>
<param-name>ENABLE_JSONP</param-name>
<param-value>true</param-value>
</context-param>
Save by pressing 'ESC' and write:
:wq!
- Reboot the machine
Set up two styles:
Make sure you have a Postgis extension on your DB, if you don't, please run the following commands using pgAdmin:
CREATE EXTENSION postgis;
CREATE EXTENSION postgis_topology;
-
Create a new workspace called 'foss4g'
-
Create a new Store (PostGIS Database type) called 'wdpa_db' with the folloing parameters:
dbtype: postgis
host: localhost
port: 5432
database: foss4g
schema: public
user: user
password: user
and publish the protected_areas layer.
-
Layer Name: protected_areas
-
Layer Title: protected_areas
-
Native SRS: 4326
-
Declared SRS: 4326
-
Apply the style protected_areas
And Save.
Plase download all the files, place them in a local folder and follow the instructions here
Please download the repository, place it in a local folder here
Create index.html file importing all the libraries and creating a the div "map"
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
<title>FOSS4G DAR ES SALAAM - CONSERVATION TOOLS</title>
<!-- include leaflet css and javascript -->
<link rel="stylesheet" href="css/leaflet.css" />
<script src="libraries/leaflet-src.js"></script>
<script src="libraries/proj4.js"></script>
<script src="libraries/proj4leaflet.js"></script>
<script src="libraries/jquery.js"></script>
<script src="libraries/highcharts.js"></script>
<script src="libraries/highcharts_more.js"></script>
<!-- include our own css -->
<link rel="stylesheet" href="css/custom.css" />
<!-- we include the javascript at the bottom, see below -->
</head>
<body>
<div id= 'banner'>
<center><h1>Free and Open Source Geospatial Tools for Conservation Planning Workshop</h1></center>
<hr>
<center><p> Example of a web application using the data produced, integrating various technologies including Postgres, GeoServer, LeafletJs and custom Javascripts.</p></center>
</div>
<div id="map"></div>
<!-- include our own javascript -->
<script src="wdpa_stats.js"></script>
</body>
</html>
#map {min-height: 800px;height: 100%;padding: 10px;}
#banner{background-image: linear-gradient(to bottom right,#ffffff,#ffffff);padding: 10px;color: #4a4f51;box-shadow: 0px -15px 5px 0px rgba(0, 0, 0, 0), 0 3px 6px rgba(0, 0, 0, 0.07);position: relative;z-index: 9999;}
#banner > img{width: 186px;float: right;margin-top: -45px;margin-right: 14px;}
#wdpa_plot_1995{position: relative;z-index: 2147483647;background: #ffffffe8;display: none;padding: 15px;margin-top: -13px;border-top: 1px solid #e0e0e0;box-shadow: 8px -5px 7px 1px rgba(0, 0, 0, 0.03), 0px 2px 0px 0px rgba(255, 255, 255, 0);}
#wdpa_plot_2015{position: relative;z-index: 2147483647;background: #ffffffe8;display: none;padding: 15px;margin-top: -13px;border-top: 1px solid #e0e0e0;box-shadow: 8px -5px 7px 1px rgba(0, 0, 0, 0.03), 0px 2px 0px 0px rgba(255, 255, 255, 0);}
#wdpa_plot_1995_title{background-color: #ffffff;margin-top: -17px;color: #261a1a;font-family: unset;font-size: 14px;font-weight: 100!important;display: none;margin-top: -19px;border-bottom: 1px solid #ebebeb;border-top: 1px solid #ebebeb;}
#wdpa_plot_2015_title{background-color: #ffffff;margin-top: -17px;color: #261a1a;font-family: unset;font-size: 14px;font-weight: 100!important;display: none;margin-top: -19px;border-bottom: 1px solid #ebebeb;border-top: 1px solid #ebebeb;}
.row {margin-right: 0px; margin-left: 0px; margin-top: -300px; position: relative; z-index: 999999;}
.row1 {margin-right: 0px; margin-left: 0px; margin-top: -320px; position: relative; z-index: 9999; z-index: 99999999; margin-bottom: 5px;}
.leaflet-popup-content-wrapper, .leaflet-popup-tip {background: #fffffff2!important; color: #516440!important;}
.leaflet-popup-content-wrapper {border-radius: 0px!important;}
- Initialise map
//Initialise map
var pixel_ratio = parseInt(window.devicePixelRatio) || 1;
var max_zoom = 16;
var tile_size = 512;
var map = L.map('map', {
}).setView([-7, 38], 6);
- Add the 2 basemaps
// Baselayers
var Esri_WorldImagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution: 'October 2017 version of the World Database on Protected Areas (WDPA)'
});
var light = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_nolabels/{z}/{x}/{y}.png', {
subdomains: 'abcd',
opacity: 1,
attribution: 'October 2017 version of the World Database on Protected Areas (WDPA)',
maxZoom: 19
}).addTo(map);
var topLayer = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}.png', {
subdomains: 'abcd',
opacity: 1,
maxZoom: 19
}).addTo(map);
- Declare the available layers
//Available Layers
var baseMaps = {"White" : light, "Esri_WorldImagery":Esri_WorldImagery};
var overlayMaps = {};
- Add Layer Control
//Add Layer Control
layerControl = L.control.layers(baseMaps, overlayMaps, null, {position: 'bottomleft'}).addTo(map);
- Layer connection to geoserver WMS using tileLayer library
// wdpa layer
var url = 'http://localhost:8082/geoserver/foss4g/wms';
var wdpa=L.tileLayer.wms(url, {
layers: 'foss4g:protected_areas',
transparent: true,
format: 'image/png',
opacity:'1',
zIndex: 33
}).addTo(map);
- Substitute the 'Available Layers' section with the following script, including now the protected areas layer
var baseMaps = {"White" : light, "Esri_WorldImagery":Esri_WorldImagery};
var overlayMaps = {'Protected Areas': wdpa};
// on click function
map.on('click', function(e) {
if (map.hasLayer(wdpa)) {
var latlng= e.latlng;
var url = getFeatureInfoUrl(
map,
wdpa,
e.latlng,
{
'info_format': 'text/javascript',
'propertyName': ' name,wdpaid',
'query_layers': 'foss4g:protected_areas ',
'format_options':'callback:getJson'
}
);
$.ajax({
jsonp: false,
url: url,
dataType: 'jsonp',
jsonpCallback: 'getJson',
success: handleJson_featureRequest
});
function handleJson_featureRequest(data)
{
if (typeof data.features[0]!=='undefined')
{
var prop=data.features[0].properties;
var filter="wdpaid='"+prop['wdpaid']+"'";
wdpa_hi.setParams({CQL_FILTER:filter});
hi_highcharts_wdpa(prop,latlng);
}
else {}
}
}
else {}
});
// get feature info function
function getFeatureInfoUrl(map, layer, latlng, params) {
var point = map.latLngToContainerPoint(latlng, map.getZoom()),
size = map.getSize(),
bounds = map.getBounds(),
sw = bounds.getSouthWest(),
ne = bounds.getNorthEast();
var defaultParams = {
request: 'GetFeatureInfo',
service: 'WMS',
srs: 'EPSG:4326',
styles: '',
version: layer._wmsVersion,
format: layer.options.format,
bbox: bounds.toBBoxString(),
height: size.y,
width: size.x,
layers: layer.options.layers,
info_format: 'text/javascript'
};
params = L.Util.extend(defaultParams, params || {});
params[params.version === '1.3.0' ? 'i' : 'x'] = point.x;
params[params.version === '1.3.0' ? 'j' : 'y'] = point.y;
return layer._url + L.Util.getParamString(params, layer._url, true);
}
// wdpa HIGLIGHTED
var url = 'http://localhost:8082/geoserver/foss4g/wms';
var wdpa_hi=L.tileLayer.wms(url, {
layers: 'foss4g:protected_areas',
transparent: true,
format: 'image/png',
opacity:'1',
styles: 'protected_areas_selected',
zIndex: 44
}).addTo(map);
wdpa_hi.setParams({CQL_FILTER:"wdpaid LIKE ''"});
// charts function
function hi_highcharts_wdpa(info,latlng){
var name=info['name'];
var wdpaid=info['wdpaid'];
var popupContent = '<center><h5>'+name+'</h5></center>';
var popup = L.popup()
.setLatLng([latlng.lat, latlng.lng])
.setContent(popupContent)
.openOn(map);
$( "#wdpa_plot_1995" ).show();
$( "#wdpa_plot_2015" ).show();
$( "#wdpa_plot_1995_title" ).show();
$( "#wdpa_plot_2015_title" ).show();
// Land Cover Change (1995-2015)
var url_wdpaid_lcc = 'http://localhost:8888/rest.py?type=fun&schema=public&obj=get_pa_lc_1995_2015¶ms=(wdpaid:'+wdpaid+')';
$.ajax({
url: url_wdpaid_lcc,
dataType: 'json',
success: function(d) {
var _1995_man;
var _1995_nat;
var _1995_wat;
var _1995_cul;
var _2015_man;
var _2015_nat;
var _2015_wat;
var _2015_cul;
var name;
$(d).each(function(i, data) {
_1995_man = parseFloat(data._1995_man);
_1995_nat = parseFloat(data._1995_nat);
_1995_wat = parseFloat(data._1995_wat);
_1995_cul = parseFloat(data._1995_cul);
_2015_man = parseFloat(data._2015_man);
_2015_nat = parseFloat(data._2015_nat);
_2015_wat = parseFloat(data._2015_wat);
_2015_cul = parseFloat(data._2015_cul);
name = data.name;
});
// Land Cover 1995
$('#wdpa_plot_1995').highcharts({
chart: {type:'bar', height: 300,
backgroundColor:'rgba(255, 255, 255, 0)',
legend: {enabled: false}
},
title: {text: null},
subtitle: {text: null},
credits: {
enabled: false,
text: '© DOPA Services',
href: 'http://dopa.jrc.ec.europa.eu/en/services'
},
xAxis: {
categories: [name]
},
yAxis: {
title: { text: null },
labels: {overflow: 'justify'}
},
series:[{
name: 'Cultivated / managed land',
color: '#d07a41',
data: [_1995_cul]
},{
name: 'Mosaic natural / managed land',
color: '#cca533',
data: [_1995_man]
},{
name: 'Natural / semi-natural land',
color: '#759a5d',
data: [_1995_nat]
},{
name: 'Water / snow and ice',
color: '#5976ab',
data: [_1995_wat]
}]
});
// Land Cover 2015
$('#wdpa_plot_2015').highcharts({
chart: {type:'bar', height: 300,
backgroundColor:'rgba(255, 255, 255, 0)',
legend: {enabled: false}
},
title: {text: null},
subtitle: {text: null},
credits: {
enabled: false,
text: '© DOPA Services',
href: 'http://dopa.jrc.ec.europa.eu/en/services'
},
xAxis: {
categories: [name]
},
yAxis: {
title: { text: null },
labels: {overflow: 'justify'}
},
series:[{
name: 'Cultivated / managed land',
color: '#d07a41',
data: [_2015_cul]
},{
name: 'Mosaic natural / managed land',
color: '#cca533',
data: [_2015_man]
},{
name: 'Natural / semi-natural land',
color: '#759a5d',
data: [_2015_nat]
},{
name: 'Water / snow and ice',
color: '#5976ab',
data: [_2015_wat]
}]
});
},
});
}
- Add these 4 lines to the bottom of the script
map.on('popupclose', function (){
$( "#wdpa_plot_1995" ).hide();
$( "#wdpa_plot_2015" ).hide();
});
- In order to render the charts 2 divs have to be added next to the div 'map'
<div class="row1">
<center><div id="wdpa_plot_1995_title" class="col-sm-6"> Land Cover 1995</div></center>
<center><div id="wdpa_plot_2015_title" class="col-sm-6">Land Cover 2015</div></center>
</div>
<div class="row">
<center><div id="wdpa_plot_1995" class="col-sm-6"></div></center>
<center><div id="wdpa_plot_2015" class="col-sm-6"></div></center>
</div>