Phi: more map widget works
- add track (flight history) layer - allow map drag and recenter on aircraft
This commit is contained in:
parent
bf4a2a2087
commit
076e437e58
5 changed files with 125 additions and 22 deletions
4
webgui/images/followAircraft.svg
Normal file
4
webgui/images/followAircraft.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 512 512" preserveAspectRatio="xMinYMin meet">
|
||||||
|
<path d="m 256.00225,133.67887 c 4.11893,0 7.55419,3.43151 7.55419,7.77922 v 45.76843 l 64.06982,35.92658 v 16.01707 l -64.06982,-18.53388 v 33.40788 l 15.10276,11.21221 v 13.2715 l -22.65957,-7.55568 -22.65283,7.55044 v -13.273 l 15.10426,-11.21222 v -33.40788 l -64.07732,18.53726 v -16.01708 l 64.07732,-35.92658 v -45.76843 c 0,-4.34771 3.42589,-7.77922 7.54819,-7.77922 z M 256,50 C 162.939,50 87.5,125.44 87.5,218.5 87.5,313 169.43,375.333 256,462 342.57,375.333 424.5,313 424.5,218.5 424.5,125.44 349.061,50 256,50 z m 0,286.958 c -68.275,0 -123.624,-55.349 -123.624,-123.624 0,-68.276 55.349,-123.624 123.624,-123.624 68.277,0 123.625,55.348 123.625,123.624 0,68.275 -55.348,123.624 -123.625,123.624 z" style="fill:#000000;stroke:#000000;stroke-width:1.87207282" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 962 B |
|
@ -9,5 +9,6 @@
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%'
|
height: '100%'
|
||||||
},
|
},
|
||||||
overlays: overlays
|
overlays: overlays,
|
||||||
|
hasFollowAircraft: true,
|
||||||
}}"></div>
|
}}"></div>
|
||||||
|
|
|
@ -5,11 +5,58 @@ define([
|
||||||
function ViewModel(params) {
|
function ViewModel(params) {
|
||||||
var self = this;
|
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 = {
|
self.overlays = {
|
||||||
|
"Track" : trackLayer,
|
||||||
|
|
||||||
"VFRMap.com Sectionals (US)" : new L.TileLayer('http://vfrmap.com/20140918/tiles/vfrc/{z}/{y}/{x}.jpg', {
|
"VFRMap.com Sectionals (US)" : new L.TileLayer('http://vfrmap.com/20140918/tiles/vfrc/{z}/{y}/{x}.jpg', {
|
||||||
maxZoom : 12,
|
maxZoom : 12,
|
||||||
minZoom : 3,
|
minZoom : 3,
|
||||||
attribution : '(c) <a href="VFRMap.com">VFRMap.com</a>',
|
attribution : '© <a target="_blank" href="http://vfrmap.com">VFRMap.com</a>',
|
||||||
tms : true,
|
tms : true,
|
||||||
opacity : 0.5,
|
opacity : 0.5,
|
||||||
bounds : L.latLngBounds(L.latLng(16.0, -179.0), L.latLng(72.0, -60.0)),
|
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', {
|
"VFRMap.com - Low IFR (US)" : new L.TileLayer('http://vfrmap.com/20140918/tiles/ifrlc/{z}/{y}/{x}.jpg', {
|
||||||
maxZoom : 12,
|
maxZoom : 12,
|
||||||
minZoom : 5,
|
minZoom : 5,
|
||||||
attribution : '© <a href="VFRMap.com">VFRMap.com</a>',
|
attribution : '© <a target="_blank" href="http://vfrmap.com">VFRMap.com</a>',
|
||||||
tms : true,
|
tms : true,
|
||||||
opacity : 0.5,
|
opacity : 0.5,
|
||||||
bounds : L.latLngBounds(L.latLng(16.0, -179.0), L.latLng(72.0, -60.0)),
|
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', {
|
'https://secais.dfs.de/static-maps/ICAO500-2014-DACH-Reprojected_01/tiles/{z}/{x}/{y}.png', {
|
||||||
minZoom : 5,
|
minZoom : 5,
|
||||||
maxZoom : 15,
|
maxZoom : 15,
|
||||||
attribution : 'Map data © <a href="http://www.dfs.de">DFS</a>',
|
attribution : '© <a target="_blank" href="http://www.dfs.de">DFS</a>',
|
||||||
bounds : L.latLngBounds(L.latLng(46.0, 5.0), L.latLng(55.1, 16.5)),
|
bounds : L.latLngBounds(L.latLng(46.0, 5.0), L.latLng(55.1, 16.5)),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -36,38 +83,49 @@ define([
|
||||||
{
|
{
|
||||||
minZoom : 5,
|
minZoom : 5,
|
||||||
maxZoom : 15,
|
maxZoom : 15,
|
||||||
attribution : 'Map data © <a href="http://www.dfs.de">DFS</a>',
|
attribution : '© <a target="_blank" href="http://www.dfs.de">DFS</a>',
|
||||||
bounds : L.latLngBounds(L.latLng(46.0, 5.0), L.latLng(55.1, 16.5)),
|
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', {
|
"France VFR" : new L.TileLayer('http://carte.f-aero.fr/oaci/{z}/{x}/{y}.png', {
|
||||||
minZoom : 5,
|
minZoom : 5,
|
||||||
maxZoom : 15,
|
maxZoom : 15,
|
||||||
attribution : 'Map data © <a href="http://carte.f-aero.fr/">F-AERO</a>',
|
attribution : '© <a target="_blank" href="http://carte.f-aero.fr/">F-AERO</a>',
|
||||||
bounds : L.latLngBounds(L.latLng(41.0, -5.3), L.latLng(51.2, 10.1)),
|
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', {
|
"France VAC Landing" : new L.TileLayer('http://carte.f-aero.fr/vac-atterrissage/{z}/{x}/{y}.png', {
|
||||||
minZoom : 5,
|
minZoom : 5,
|
||||||
maxZoom : 15,
|
maxZoom : 15,
|
||||||
attribution : 'Map data © <a href="http://carte.f-aero.fr/">F-AERO</a>',
|
attribution : '© <a target="_blank" href="http://carte.f-aero.fr/">F-AERO</a>',
|
||||||
bounds : L.latLngBounds(L.latLng(41.0, -5.3), L.latLng(51.2, 10.1)),
|
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', {
|
"France VAC Approach" : new L.TileLayer('http://carte.f-aero.fr/vac-approche/{z}/{x}/{y}.png', {
|
||||||
minZoom : 5,
|
minZoom : 5,
|
||||||
maxZoom : 15,
|
maxZoom : 15,
|
||||||
attribution : 'Map data © <a href="http://carte.f-aero.fr/">F-AERO</a>',
|
attribution : '© <a target="_blank" href="http://carte.f-aero.fr/">F-AERO</a>',
|
||||||
bounds : L.latLngBounds(L.latLng(41.0, -5.3), L.latLng(51.2, 10.1)),
|
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 : '© <a target="_blank" href="http://openweathermap.org/">open weather map</a>',
|
||||||
|
}),
|
||||||
|
|
||||||
"Precipitation" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/precipitation/{z}/{x}/{y}.png', {
|
"Precipitation" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/precipitation/{z}/{x}/{y}.png', {
|
||||||
maxZoom : 14,
|
maxZoom : 14,
|
||||||
minZoom : 0,
|
minZoom : 0,
|
||||||
subdomains : '12',
|
subdomains : '12',
|
||||||
format : 'image/png',
|
format : 'image/png',
|
||||||
transparent : true,
|
transparent : true,
|
||||||
opacity : 0.5
|
opacity : 0.5,
|
||||||
|
attribution : '© <a target="_blank" href="http://openweathermap.org/">open weather map</a>',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
"Isobares" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/pressure_cntr/{z}/{x}/{y}.png', {
|
"Isobares" : new L.TileLayer('http://{s}.tile.openweathermap.org/map/pressure_cntr/{z}/{x}/{y}.png', {
|
||||||
|
@ -76,7 +134,18 @@ define([
|
||||||
subdomains : '12',
|
subdomains : '12',
|
||||||
format : 'image/png',
|
format : 'image/png',
|
||||||
transparent : true,
|
transparent : true,
|
||||||
opacity : 0.5
|
opacity : 0.5,
|
||||||
|
attribution : '© <a target="_blank" href="http://openweathermap.org/">open weather map</a>',
|
||||||
|
}),
|
||||||
|
|
||||||
|
"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 : '© <a target="_blank" href="http://openweathermap.org/">open weather map</a>',
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,4 +37,13 @@
|
||||||
.aircraft-marker span {
|
.aircraft-marker span {
|
||||||
padding-left: 0.5em;
|
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;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -10,6 +10,10 @@ define(
|
||||||
self.element = componentInfo.element;
|
self.element = componentInfo.element;
|
||||||
self.followAircraft = ko.observable(true);
|
self.followAircraft = ko.observable(true);
|
||||||
|
|
||||||
|
self.toggleFollowAircraft = function(a) {
|
||||||
|
self.followAircraft(!self.followAircraft());
|
||||||
|
}
|
||||||
|
|
||||||
self.altitude = ko.observable(0).extend({
|
self.altitude = ko.observable(0).extend({
|
||||||
fgprop : 'altitude'
|
fgprop : 'altitude'
|
||||||
});
|
});
|
||||||
|
@ -32,32 +36,48 @@ define(
|
||||||
}
|
}
|
||||||
|
|
||||||
var MapOptions = {
|
var MapOptions = {
|
||||||
attributionControl: false,
|
attributionControl : false,
|
||||||
|
dragging: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if( params && params.map ) {
|
if (params && params.map) {
|
||||||
for( var p in params.map ) {
|
for ( var p in params.map) {
|
||||||
MapOptions[p] = params.map[p];
|
MapOptions[p] = params.map[p];
|
||||||
}
|
}
|
||||||
MapOptions = params.map;
|
MapOptions = params.map;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.map = leaflet.map(self.element,MapOptions).setView([
|
self.map = leaflet.map(self.element, MapOptions).setView([
|
||||||
53.5, 10.0
|
53.5, 10.0
|
||||||
], MapOptions.zoom || 13);
|
], MapOptions.zoom || 13);
|
||||||
|
|
||||||
var baseLayers = {
|
var baseLayers = {
|
||||||
"OpenStreetMaps" : new leaflet.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
"OpenStreetMaps" : new leaflet.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
maxZoom : 18,
|
maxZoom : 18,
|
||||||
attribution : 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors'
|
attribution : 'Map data © <a target="_blank" href="http://openstreetmap.org">OpenStreetMap</a> contributors'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
self.map.addLayer(baseLayers["OpenStreetMaps"]);
|
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 = '<img src="images/followAircraft.svg" title="Center Map on Aircraft Position" data-bind="click: toggleFollowAircraft"/>';
|
||||||
|
return this._div;
|
||||||
|
}
|
||||||
|
followAircraftControl.addTo(self.map);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params && params.overlays) {
|
||||||
L.control.layers(baseLayers, params.overlays).addTo(self.map);
|
L.control.layers(baseLayers, params.overlays).addTo(self.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
L.RotatedMarker = L.Marker.extend({
|
L.RotatedMarker = L.Marker.extend({
|
||||||
options : {
|
options : {
|
||||||
angle : 0
|
angle : 0
|
||||||
|
|
Loading…
Add table
Reference in a new issue