Skip to content

Instantly share code, notes, and snippets.

@ajzeigert
Created November 3, 2015 21:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ajzeigert/89e12126dc6047c663b8 to your computer and use it in GitHub Desktop.
Save ajzeigert/89e12126dc6047c663b8 to your computer and use it in GitHub Desktop.
Basic mapbox gl js map with sorta data-drive styling and interactivity
<!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>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View raw

(Sorry about that, but we can’t show files that are this big right now.)

Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment