diff --git a/webgui/images/followAircraft.svg b/webgui/images/followAircraft.svg
new file mode 100644
index 000000000..3758ab78e
--- /dev/null
+++ b/webgui/images/followAircraft.svg
@@ -0,0 +1,4 @@
+
+
diff --git a/webgui/topics/Map.html b/webgui/topics/Map.html
index 98932d018..961fae5fd 100644
--- a/webgui/topics/Map.html
+++ b/webgui/topics/Map.html
@@ -9,5 +9,6 @@
width: '100%',
height: '100%'
},
- overlays: overlays
+ overlays: overlays,
+ hasFollowAircraft: true,
}}">
diff --git a/webgui/topics/Map.js b/webgui/topics/Map.js
index f506d6900..3431f4a13 100644
--- a/webgui/topics/Map.js
+++ b/webgui/topics/Map.js
@@ -5,11 +5,58 @@ define([
function ViewModel(params) {
var self = this;
+ var trackLayer = new L.GeoJSON(null, {});
+ trackLayer.update = function(id) {
+ var self = this;
+ if (id != self.updateId)
+ return;
+
+ var url = "/flighthistory/track.json";
+
+ var jqxhr = $.get(url).done(function(data) {
+ self.clearLayers();
+ self.addData(data);
+ }).fail(function() {
+ var r = confirm("Error loading flight history. Retry?");
+ if (!r)
+ self.updateId++;
+ }).always(function() {
+ });
+
+ setTimeout(function() {
+ self.update(id)
+ }, 10000);
+ }
+
+ trackLayer.updateId = 0;
+ trackLayer.start = function() {
+ this.update(++this.updateId);
+ return this;
+ }
+
+ trackLayer.stop = function() {
+ ++this.updateId;
+ return this;
+ }
+
+ trackLayer.onAdd = function(map) {
+ this.start();
+ return L.GeoJSON.prototype.onAdd.call(this, map);
+
+ }
+
+ trackLayer.onRemove = function(map) {
+ this.stop();
+ return L.GeoJSON.prototype.onRemove.call(this, map);
+ }
+
self.overlays = {
+ "Track" : trackLayer,
+
"VFRMap.com Sectionals (US)" : new L.TileLayer('http://vfrmap.com/20140918/tiles/vfrc/{z}/{y}/{x}.jpg', {
maxZoom : 12,
minZoom : 3,
- attribution : '(c) VFRMap.com',
+ attribution : '© VFRMap.com',
tms : true,
opacity : 0.5,
bounds : L.latLngBounds(L.latLng(16.0, -179.0), L.latLng(72.0, -60.0)),
@@ -18,7 +65,7 @@ define([
"VFRMap.com - Low IFR (US)" : new L.TileLayer('http://vfrmap.com/20140918/tiles/ifrlc/{z}/{y}/{x}.jpg', {
maxZoom : 12,
minZoom : 5,
- attribution : '© VFRMap.com',
+ attribution : '© VFRMap.com',
tms : true,
opacity : 0.5,
bounds : L.latLngBounds(L.latLng(16.0, -179.0), L.latLng(72.0, -60.0)),
@@ -28,7 +75,7 @@ define([
'https://secais.dfs.de/static-maps/ICAO500-2014-DACH-Reprojected_01/tiles/{z}/{x}/{y}.png', {
minZoom : 5,
maxZoom : 15,
- attribution : 'Map data © DFS',
+ attribution : '© DFS',
bounds : L.latLngBounds(L.latLng(46.0, 5.0), L.latLng(55.1, 16.5)),
}),
@@ -36,38 +83,49 @@ define([
{
minZoom : 5,
maxZoom : 15,
- attribution : 'Map data © DFS',
+ attribution : '© DFS',
bounds : L.latLngBounds(L.latLng(46.0, 5.0), L.latLng(55.1, 16.5)),
}),
"France VFR" : new L.TileLayer('http://carte.f-aero.fr/oaci/{z}/{x}/{y}.png', {
minZoom : 5,
maxZoom : 15,
- attribution : 'Map data © F-AERO',
+ attribution : '© F-AERO',
bounds : L.latLngBounds(L.latLng(41.0, -5.3), L.latLng(51.2, 10.1)),
}),
"France VAC Landing" : new L.TileLayer('http://carte.f-aero.fr/vac-atterrissage/{z}/{x}/{y}.png', {
minZoom : 5,
maxZoom : 15,
- attribution : 'Map data © F-AERO',
+ attribution : '© F-AERO',
bounds : L.latLngBounds(L.latLng(41.0, -5.3), L.latLng(51.2, 10.1)),
}),
"France VAC Approach" : new L.TileLayer('http://carte.f-aero.fr/vac-approche/{z}/{x}/{y}.png', {
minZoom : 5,
maxZoom : 15,
- attribution : 'Map data © F-AERO',
+ attribution : '© F-AERO',
bounds : L.latLngBounds(L.latLng(41.0, -5.3), L.latLng(51.2, 10.1)),
}),
+ "Clouds" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/clouds/{z}/{x}/{y}.png', {
+ maxZoom : 14,
+ minZoom : 0,
+ subdomains : '12',
+ format : 'image/png',
+ transparent : true,
+ opacity : 0.5,
+ attribution : '© open weather map',
+ }),
+
"Precipitation" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/precipitation/{z}/{x}/{y}.png', {
maxZoom : 14,
minZoom : 0,
subdomains : '12',
format : 'image/png',
transparent : true,
- opacity : 0.5
+ opacity : 0.5,
+ attribution : '© open weather map',
}),
"Isobares" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/pressure_cntr/{z}/{x}/{y}.png', {
@@ -76,7 +134,18 @@ define([
subdomains : '12',
format : 'image/png',
transparent : true,
- opacity : 0.5
+ opacity : 0.5,
+ attribution : '© open weather map',
+ }),
+
+ "Wind" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/wind/{z}/{x}/{y}.png', {
+ maxZoom : 7,
+ minZoom : 0,
+ subdomains : '12',
+ format : 'image/png',
+ transparent : true,
+ opacity : 0.5,
+ attribution : '© open weather map',
}),
}
}
diff --git a/webgui/widgets/map.html b/webgui/widgets/map.html
index c524afb41..9fe7fc033 100644
--- a/webgui/widgets/map.html
+++ b/webgui/widgets/map.html
@@ -37,4 +37,13 @@
.aircraft-marker span {
padding-left: 0.5em;
}
+
+.followAircraft {
+ background: white;
+ background: rgba(255, 255, 255, 0.8);
+ box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
+ border-radius: 5px;
+ width: 40px;
+ height: 40px;
+}
diff --git a/webgui/widgets/map.js b/webgui/widgets/map.js
index 603b24909..262faaf8b 100644
--- a/webgui/widgets/map.js
+++ b/webgui/widgets/map.js
@@ -10,6 +10,10 @@ define(
self.element = componentInfo.element;
self.followAircraft = ko.observable(true);
+ self.toggleFollowAircraft = function(a) {
+ self.followAircraft(!self.followAircraft());
+ }
+
self.altitude = ko.observable(0).extend({
fgprop : 'altitude'
});
@@ -32,32 +36,48 @@ define(
}
var MapOptions = {
- attributionControl: false,
+ attributionControl : false,
+ dragging: false,
};
-
- if( params && params.map ) {
- for( var p in params.map ) {
+
+ if (params && params.map) {
+ for ( var p in params.map) {
MapOptions[p] = params.map[p];
}
MapOptions = params.map;
}
- self.map = leaflet.map(self.element,MapOptions).setView([
+ self.map = leaflet.map(self.element, MapOptions).setView([
53.5, 10.0
], MapOptions.zoom || 13);
var baseLayers = {
- "OpenStreetMaps" : new leaflet.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
- maxZoom : 18,
- attribution : 'Map data © OpenStreetMap contributors'
- })
+ "OpenStreetMaps" : new leaflet.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
+ maxZoom : 18,
+ attribution : 'Map data © OpenStreetMap contributors'
+ })
}
self.map.addLayer(baseLayers["OpenStreetMaps"]);
-
- if( params && params.overlays ) {
+
+ if (params && params.hasFollowAircraft ) {
+ self.map.on('dragstart', function(e) {
+ self.followAircraft(false);
+ });
+
+ var followAircraftControl = L.control();
+
+ followAircraftControl.onAdd = function(map) {
+ this._div = L.DomUtil.create('div', 'followAircraft');
+ this._div.innerHTML = '
';
+ return this._div;
+ }
+ followAircraftControl.addTo(self.map);
+ }
+
+ if (params && params.overlays) {
L.control.layers(baseLayers, params.overlays).addTo(self.map);
}
-
+
L.RotatedMarker = L.Marker.extend({
options : {
angle : 0