xxxxxxxxxx
<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="https://cdn-geoweb.s3.amazonaws.com/terraformer/1.0.4/terraformer.min.js"></script>
<script src="https://cdn-geoweb.s3.amazonaws.com/terraformer-arcgis-parser/1.0.4/terraformer-arcgis-parser.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
}
});
// This is the big one, grabs the ESRI data, converts to geojson, loads a layer for each feature, styled to order
$.ajax({
url: 'https://tmservices1.esri.com/arcgis/rest/services/LiveFeeds/NOAA_METAR_current_wind_speed_direction/MapServer/0/query?where=objectId%3E%3D0&text=&objectIds=&time=&geometry=-130%2C20%2C-58%2C52&geometryType=esriGeometryEnvelope&inSR=4326&spatialRel=esriSpatialRelEnvelopeIntersects&relationParam=&outFields=*&returnGeometry=true&maxAllowableOffset=&geometryPrecision=&outSR=4326&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&returnDistinctValues=false&f=json',
dataType: 'json'})
.done(function(windresponse){
var FeatureCollection = {
type: "FeatureCollection",
features: []
}
for(var i = 0; i < windresponse.features.length; i++){
var feature = Terraformer.ArcGIS.parse(windresponse.features[i]);
feature.id = i;
FeatureCollection.features.push(feature);
}
var source = new mapboxgl.GeoJSONSource({
data: FeatureCollection
})
// Add the newly created geojson as a source
map.addSource('wind', source);
// Function to translate wind speed to proper text size
var windSize = function(feature){
var a = feature.properties.WIND_SPEED
if (a > 0 && a <= 11 ) {
return 16;
}
else if (a > 11 && a <= 20) {
return 18;
}
else if (a > 20 && a <= 28) {
return 20;
}
else if (a > 28 && a <= 39) {
return 22;
}
else if (a > 39 && a <= 94) {
return 24;
}
else {
return 0;
}
}
// Function to translate wind speed to proper text color
var windColor = function(feature){
var a = feature.properties.WIND_SPEED
if (a > 0 && a <= 11 ) {
return 'rgb(191, 184, 64)';
}
else if (a > 11 && a <= 20) {
return 'rgb(242, 203, 103)';
}
else if (a > 20 && a <= 28) {
return 'rgb(237, 162, 62)';
}
else if (a > 28 && a <= 39) {
return 'rgb(219, 94, 49)';
}
else if (a > 39 && a <= 94) {
return 'rgb(168, 0, 0)';
}
else {
return 'rgb(255,255,255)';
}
}
// Build an array of layers for each features
var windLayers = [];
// Build a layer for each feature and push it into the empty array
var i;
for (i = 0; i < FeatureCollection.features.length; i++) {
var layer = {
"id": 'wind' + i,
"type": 'symbol',
"source": 'wind',
"layout": {
"text-field": FeatureCollection.features[i].properties.WIND_SPEED > 0 ? 'E' : '5',
"text-font": ['ESRI Dimensioning Regular'],
"text-rotate": FeatureCollection.features[i].properties.WIND_DIRECT,
"text-rotation-alignment": 'map',
"text-size": windSize(FeatureCollection.features[i])
},
"paint": {
"text-color": windColor(FeatureCollection.features[i])
},
"filter": ['==', 'OBJECTID', FeatureCollection.features[i].properties.OBJECTID]
};
windLayers.push(layer);
}
// console.log(windLayers)
map.batch(function(batch){
var i;
for (i = 0; i < windLayers.length; i++) {
batch.addLayer(windLayers[i])
}
})
}); // End of esri call
// 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){
// console.log(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>
Modified http://cdn-geoweb.s3.amazonaws.com/terraformer/1.0.4/terraformer.min.js to a secure url
Modified http://cdn-geoweb.s3.amazonaws.com/terraformer-arcgis-parser/1.0.4/terraformer-arcgis-parser.min.js to a secure url
https://api.tiles.mapbox.com/mapbox-gl-js/v0.11.1/mapbox-gl.js
https://code.jquery.com/jquery-1.11.3.min.js
https://cdn-geoweb.s3.amazonaws.com/terraformer/1.0.4/terraformer.min.js
https://cdn-geoweb.s3.amazonaws.com/terraformer-arcgis-parser/1.0.4/terraformer-arcgis-parser.min.js