From 076e437e5852a4b893ba09c327b570c09fb1b8e1 Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Wed, 25 Feb 2015 21:42:46 +0100 Subject: [PATCH] Phi: more map widget works - add track (flight history) layer - allow map drag and recenter on aircraft --- webgui/images/followAircraft.svg | 4 ++ webgui/topics/Map.html | 3 +- webgui/topics/Map.js | 87 ++++++++++++++++++++++++++++---- webgui/widgets/map.html | 9 ++++ webgui/widgets/map.js | 44 +++++++++++----- 5 files changed, 125 insertions(+), 22 deletions(-) create mode 100644 webgui/images/followAircraft.svg 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