Created
November 3, 2015 21:28
-
-
Save ajzeigert/89e12126dc6047c663b8 to your computer and use it in GitHub Desktop.
Basic mapbox gl js map with sorta data-drive styling and interactivity
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> | |
<meta charset='utf-8' /> | |
<title>GAS PIRATE</title> | |
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> | |
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.11.1/mapbox-gl.js'></script> | |
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.11.1/mapbox-gl.css' rel='stylesheet' /> | |
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script> | |
<!-- <script src='colorbrewer.js'></script>--> | |
<style> | |
html, body { | |
font-family: sans-serif; | |
padding: 0; | |
margin: 0; | |
} | |
p { | |
margin: 0; | |
} | |
#map { | |
width: 100vw; | |
height: 100vh; | |
} | |
#timeslider { | |
background: rgba(255,255,255,0.5); | |
position: absolute; | |
right: 10px; | |
top: 10px; | |
padding: 10px; | |
width: 400px; | |
} | |
#timeslider input { | |
width: 100%; | |
} | |
#timeslider h3, h4 { | |
margin: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="map"></div> | |
<div id="timeslider"> | |
<h4>Slide to select 3 nearest readings to selected time</h4> | |
<input type='range' min=0 max=100 step=10> | |
<h3>Selected time</h3> | |
</div> | |
<script> | |
// Smartmine mapbox token | |
mapboxgl.accessToken = 'pk.eyJ1Ijoic21hcnRtaW5lIiwiYSI6Imt6TUp0cEEifQ.9MrwD6GRlEGj9OTNN-bsRw'; | |
// Smartmine map style | |
var geodark = 'mapbox://styles/smartmine/cigdv27lk00029hkt6leqc9yz'; | |
// Fire up the map | |
var map = new mapboxgl.Map({ | |
container: 'map', // container id | |
style: geodark, //stylesheet location | |
center: [-118.25, 34.05], // starting position | |
zoom: 10, // starting zoom | |
minzoom: 10, | |
hash: true | |
}); | |
// Add a new basic controller | |
map.addControl(new mapboxgl.Navigation({position: 'top-left'})); | |
// After the map style loads, do this stuff | |
map.on('style.load', function() { | |
// Add the high-pressure line source | |
map.addSource("high-pressure", { | |
"type": 'geojson', | |
"data": 'pipeline_hp.json' | |
}); | |
// Add the high-pressure line style | |
map.addLayer({ | |
"id": 'high-pressure', | |
"type": 'line', | |
"source": 'high-pressure', | |
"layout": { | |
"line-join": 'round', | |
"line-cap": 'round', | |
}, | |
"paint": { | |
"line-color": "#7aa0b4", | |
"line-width": '4', | |
"line-blur": 3 | |
} | |
}); | |
// Add the transmission line source | |
map.addSource("transmission", { | |
"type": 'geojson', | |
"data": 'pipeline_t.json' | |
}); | |
// Add the transmission line style | |
map.addLayer({ | |
"id": 'transmission', | |
"type": 'line', | |
"source": 'transmission', | |
"layout": { | |
"line-join": 'round', | |
"line-cap": 'round', | |
}, | |
"paint": { | |
"line-color": "#013f62", | |
"line-width": '4', | |
"line-blur": 3 | |
} | |
}); | |
// Load the readings geojson using ajax, because we want to manipulate the object before handing to mapbox gl js | |
// Empty readings object so it's available outside the ajax context | |
var readings = {}; | |
// Load the geojson, and execute a function on it when done | |
$.ajax({ | |
url: 'readings.geojson', | |
dataType: 'json'}) | |
.done(function(data){ | |
// Set readings to the data from geojson | |
readings = data; | |
// Since this geojson has no object ID, lets make one | |
for (i = 0; i < readings.features.length; i++){ | |
readings.features[i].properties.readingID = i; | |
} | |
// Sort readings by sensor time | |
readings.features.sort(function(a,b){ | |
a = new Date(a.properties.sensorTime); | |
b = new Date(b.properties.sensorTime); | |
return a>b ? 1 : a<b ? -1 : 0; | |
}); | |
// Declare oldest and newest reading | |
var oldestReading = new Date(readings.features[0].properties.sensorTime); | |
var newestReading = new Date(readings.features[readings.features.length - 1].properties.sensorTime); | |
// Add our new geojson as a source | |
map.addSource("readings", { | |
"type": 'geojson', | |
"data": readings | |
}); | |
// Because as of v8, there is no support in Mapbox GL js for data-driven styling, | |
// this code creates new layers for each "style" and filters the appropriate symbols | |
// Add a new layer for gray symbols and filter based on LEL readings | |
map.addLayer({ | |
"id": 'readings-normal', | |
"type": 'circle', | |
"source": 'readings', | |
"paint": { | |
"circle-radius": 8, | |
"circle-color": '#d8d8d8', | |
"circle-opacity": 0.5 | |
}, | |
"filter": ['<=', 'percentLEL', 100], | |
"interactive": 'true' | |
}); | |
// Add a new layer for red symbols and filter based on LEL readings | |
map.addLayer({ | |
"id": 'readings-warning', | |
"type": 'circle', | |
"source": 'readings', | |
"paint": { | |
"circle-radius": 12, | |
"circle-color": '#F03B20', | |
"circle-opacity": 0.75 | |
}, | |
"filter": ['>=', 'percentLEL', 100], | |
"interactive": 'true' | |
}); | |
// Add a new layer for item labels using the readings source | |
map.addLayer({ | |
"id": 'readings-label', | |
"type": 'symbol', | |
"source": 'readings', | |
"layout": { | |
"text-field": 'Device ID: {deviceID}', | |
"text-anchor": 'bottom-left', | |
"text-size": 14, | |
"text-font": ['Open Sans Bold'], | |
"text-offset": [0.5,-0.5] | |
}, | |
"paint": { | |
'text-color': '#fff' | |
} | |
}) | |
// Set the range input min and max to the oldest and newest readings | |
$('#timeslider input').attr('min', Date.parse(oldestReading)).attr('max', Date.parse(newestReading)); | |
// When there's a change event on the slider... | |
$('#timeslider input').on('change', function(){ | |
// Grab the value of the slider | |
var displayTime = $('#timeslider input')[0].value; | |
// Make displayTime a date object | |
displayTime = new Date(+displayTime); | |
// Put that date into the slider box | |
$('#timeslider h3').html(displayTime); | |
// Gimme the raw javascript time | |
var compareTime = Date.parse(displayTime); | |
// Check all dates in the features against the selected time note the difference | |
for (i = 0; i < readings.features.length; i++){ | |
var sensorTime = new Date(readings.features[i].properties.sensorTime); | |
var difference = Math.abs(compareTime - sensorTime); | |
readings.features[i].properties.difference = difference; | |
} | |
// Re-sort the readings based on the shortest difference | |
readings.features.sort(function(a,b){ | |
a = a.properties.difference; | |
b = b.properties.difference; | |
return a>b ? 1 : a<b ? -1 : 0; | |
}); | |
// Create three filter sets for the three readings layers (including labels) | |
// Only show the top three features, which should have the lowest difference | |
var filtersNormal = [ | |
'all', | |
['in', 'readingID', readings.features[0].properties.readingID, readings.features[1].properties.readingID, readings.features[2].properties.readingID], | |
['<=', 'percentLEL', 100] | |
]; | |
var filtersWarning = [ | |
'all', | |
['in', 'readingID', readings.features[0].properties.readingID, readings.features[1].properties.readingID, readings.features[2].properties.readingID], | |
['>=', 'percentLEL', 100] | |
]; | |
var filtersLabel = ['in', 'readingID', readings.features[0].properties.readingID, readings.features[1].properties.readingID, readings.features[2].properties.readingID]; | |
// Update the layers with the new filters | |
map.setFilter('readings-warning', filtersWarning); | |
map.setFilter('readings-normal', filtersNormal); | |
map.setFilter('readings-label', filtersLabel); | |
}); // End input on change function | |
}); // End ajax done function | |
// Get the feature info when clicked | |
map.on('click', function (e) { | |
map.featuresAt(e.point, {radius: 5, layer: ['readings-warning', 'readings-normal']}, function (err, features) { | |
if (err) throw err; | |
console.log(features[0]); | |
var popup = new mapboxgl.Popup() | |
.setLngLat([features[0].properties.lon, features[0].properties.lat]) // | |
.setHTML('<p><strong>Percent LEL: </strong>' + features[0].properties.percentLEL + '</p>' | |
+ '<p><strong>Temp (C): </strong>' + features[0].properties.temp + '</p>') | |
.addTo(map) | |
}); | |
}); | |
}); // End mapbox on load function | |
</script> | |
</body> | |
</html> |
View raw
(Sorry about that, but we can’t show files that are this big right now.)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment