2015-02-13 15:24:41 +00:00
|
|
|
define(
|
|
|
|
[
|
2015-07-30 19:03:06 +00:00
|
|
|
'knockout', 'jquery', 'leaflet', 'text!./map.html'
|
2015-02-13 15:24:41 +00:00
|
|
|
],
|
2015-07-30 19:03:06 +00:00
|
|
|
function(ko, jquery, leaflet, htmlString ) {
|
2015-08-07 12:17:05 +00:00
|
|
|
//TODO: Don't extend Marker but Icon
|
|
|
|
|
2015-07-30 19:03:06 +00:00
|
|
|
if( !L.AircraftMarker ) {
|
|
|
|
L.AircraftMarker = L.Marker
|
|
|
|
.extend({
|
|
|
|
options : {
|
|
|
|
clickable : false,
|
|
|
|
keyboard : false,
|
|
|
|
zIndexOffset : 10000,
|
|
|
|
},
|
2015-02-13 15:24:41 +00:00
|
|
|
|
2015-07-30 19:03:06 +00:00
|
|
|
initialize : function(latlng, options) {
|
2015-08-07 12:17:05 +00:00
|
|
|
var extraIconClass = '';
|
|
|
|
if( options && options.className ) {
|
|
|
|
extraIconClass = ' ' + options.className;
|
|
|
|
}
|
2015-07-30 19:03:06 +00:00
|
|
|
L.Marker.prototype.initialize(latlng, options);
|
|
|
|
L.Util.setOptions(this, options);
|
2015-08-07 12:17:05 +00:00
|
|
|
this.setIcon( L.divIcon({
|
|
|
|
iconSize: null,
|
|
|
|
className : 'aircraft-marker-icon' + extraIconClass,
|
|
|
|
html :
|
|
|
|
'<div data-bind="component: { ' +
|
|
|
|
'name: \'AircraftMarker\', ' +
|
|
|
|
'params: { rotate: heading, label: labelLines } ' +
|
|
|
|
'}"></div>',
|
|
|
|
}));
|
2015-07-30 19:03:06 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
});
|
2015-02-13 15:24:41 +00:00
|
|
|
|
2015-07-30 19:03:06 +00:00
|
|
|
L.aircraftMarker = function(latlng, options) {
|
|
|
|
return new L.AircraftMarker(latlng, options);
|
2015-07-08 11:27:54 +00:00
|
|
|
}
|
2015-07-30 19:03:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function ViewModel(params, componentInfo) {
|
|
|
|
var self = this;
|
2015-07-08 11:27:54 +00:00
|
|
|
|
2015-02-13 15:24:41 +00:00
|
|
|
self.element = componentInfo.element;
|
|
|
|
self.followAircraft = ko.observable(true);
|
|
|
|
|
2015-02-25 20:42:46 +00:00
|
|
|
self.toggleFollowAircraft = function(a) {
|
|
|
|
self.followAircraft(!self.followAircraft());
|
|
|
|
}
|
2015-07-30 19:03:06 +00:00
|
|
|
|
2015-02-13 15:24:41 +00:00
|
|
|
self.altitude = ko.observable(0).extend({
|
|
|
|
fgprop : 'altitude'
|
|
|
|
});
|
|
|
|
|
|
|
|
self.tas = ko.observable(0).extend({
|
2015-02-16 13:51:54 +00:00
|
|
|
fgprop : 'groundspeed'
|
2015-02-13 15:24:41 +00:00
|
|
|
});
|
|
|
|
|
2015-02-25 08:35:23 +00:00
|
|
|
if (params && params.css) {
|
2015-02-25 08:27:19 +00:00
|
|
|
for ( var p in params.css) {
|
2015-03-27 23:39:20 +00:00
|
|
|
jquery(self.element).css(p, params.css[p]);
|
2015-02-25 08:27:19 +00:00
|
|
|
}
|
2015-02-25 08:35:23 +00:00
|
|
|
}
|
2015-03-27 23:39:20 +00:00
|
|
|
if (jquery(self.element).height() < 1) {
|
|
|
|
jquery(self.element).css("min-height", jquery(self.element).width());
|
2015-02-25 08:35:23 +00:00
|
|
|
}
|
2015-02-13 15:24:41 +00:00
|
|
|
|
2015-02-25 15:44:47 +00:00
|
|
|
var MapOptions = {
|
2015-02-25 20:42:46 +00:00
|
|
|
attributionControl : false,
|
|
|
|
dragging: false,
|
2015-02-25 15:44:47 +00:00
|
|
|
};
|
2015-02-25 20:42:46 +00:00
|
|
|
|
|
|
|
if (params && params.map) {
|
|
|
|
for ( var p in params.map) {
|
2015-02-25 15:44:47 +00:00
|
|
|
MapOptions[p] = params.map[p];
|
|
|
|
}
|
|
|
|
MapOptions = params.map;
|
|
|
|
}
|
2015-02-13 15:24:41 +00:00
|
|
|
|
2015-02-25 20:42:46 +00:00
|
|
|
self.map = leaflet.map(self.element, MapOptions).setView([
|
2015-02-25 15:44:47 +00:00
|
|
|
53.5, 10.0
|
|
|
|
], MapOptions.zoom || 13);
|
2015-02-13 15:24:41 +00:00
|
|
|
|
2015-03-09 19:59:17 +00:00
|
|
|
if( params && params.on ) {
|
|
|
|
for ( var p in params.on ) {
|
|
|
|
var h = params.on[p];
|
|
|
|
if( typeof(h) === 'function' )
|
|
|
|
self.map.on(p,h);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-25 15:44:47 +00:00
|
|
|
var baseLayers = {
|
2015-02-25 20:42:46 +00:00
|
|
|
"OpenStreetMaps" : new leaflet.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
|
|
maxZoom : 18,
|
|
|
|
attribution : 'Map data © <a target="_blank" href="http://openstreetmap.org">OpenStreetMap</a> contributors'
|
|
|
|
})
|
2015-02-25 15:44:47 +00:00
|
|
|
}
|
|
|
|
self.map.addLayer(baseLayers["OpenStreetMaps"]);
|
2015-02-25 20:42:46 +00:00
|
|
|
|
|
|
|
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) {
|
2015-02-25 15:44:47 +00:00
|
|
|
L.control.layers(baseLayers, params.overlays).addTo(self.map);
|
|
|
|
}
|
2015-02-25 20:42:46 +00:00
|
|
|
|
2015-03-10 20:48:11 +00:00
|
|
|
if( params && params.selectedOverlays && params.overlays ) {
|
|
|
|
params.selectedOverlays.forEach(function(ovl) {
|
|
|
|
params.overlays[ovl].addTo(self.map);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-03-05 18:40:38 +00:00
|
|
|
if (params && params.scale) {
|
|
|
|
L.control.scale(params.scale).addTo(self.map);
|
|
|
|
}
|
|
|
|
|
2015-08-07 12:17:05 +00:00
|
|
|
var aircraftMarker = L.aircraftMarker(self.map.getCenter(), { className: 'you-aircraft-marker-icon' });
|
2015-02-13 15:24:41 +00:00
|
|
|
|
|
|
|
aircraftMarker.addTo(self.map);
|
|
|
|
|
2015-02-13 15:50:29 +00:00
|
|
|
var aircraftTrack = L.polyline([], {
|
|
|
|
color : 'red'
|
|
|
|
}).addTo(self.map);
|
|
|
|
|
2015-02-13 15:24:41 +00:00
|
|
|
self.latitude = ko.observable(0).extend({
|
|
|
|
fgprop : 'latitude'
|
|
|
|
});
|
|
|
|
|
|
|
|
self.longitude = ko.observable(0).extend({
|
|
|
|
fgprop : 'longitude'
|
|
|
|
});
|
|
|
|
|
|
|
|
self.heading = ko.observable(0).extend({
|
2015-02-27 15:29:26 +00:00
|
|
|
fgprop : 'true-heading'
|
2015-02-13 15:24:41 +00:00
|
|
|
});
|
|
|
|
|
2015-03-03 12:30:13 +00:00
|
|
|
self.position = ko.pureComputed(function() {
|
2015-02-13 15:24:41 +00:00
|
|
|
return leaflet.latLng(self.latitude(), self.longitude());
|
|
|
|
}).extend({
|
|
|
|
rateLimit : 200
|
|
|
|
});
|
|
|
|
|
|
|
|
self.position.subscribe(function(newValue) {
|
|
|
|
aircraftMarker.setLatLng(newValue);
|
|
|
|
});
|
|
|
|
|
2015-07-30 19:03:06 +00:00
|
|
|
self.labelLines = [
|
|
|
|
'You',
|
|
|
|
ko.pureComputed(function() {
|
|
|
|
var h = Math.round(self.heading());
|
|
|
|
var t = Math.round(self.tas());
|
|
|
|
var a = Math.round(self.altitude());
|
|
|
|
return '' + h + "T " + t + "KTAS " + a + "ft";
|
|
|
|
}),
|
|
|
|
];
|
2015-02-13 15:24:41 +00:00
|
|
|
|
2015-03-03 12:30:13 +00:00
|
|
|
self.mapCenter = ko.pureComputed(function() {
|
2015-02-13 15:24:41 +00:00
|
|
|
return leaflet.latLng(self.latitude(), self.longitude());
|
|
|
|
}).extend({
|
|
|
|
rateLimit : 2000
|
|
|
|
});
|
|
|
|
|
2015-02-13 15:50:29 +00:00
|
|
|
self.aircraftTrailLength = 60;
|
|
|
|
|
2015-02-13 15:24:41 +00:00
|
|
|
self.mapCenter.subscribe(function(newValue) {
|
|
|
|
if (self.followAircraft()) {
|
|
|
|
self.map.setView(newValue);
|
|
|
|
}
|
2015-02-13 15:50:29 +00:00
|
|
|
|
|
|
|
var trail = aircraftTrack.getLatLngs();
|
|
|
|
while (trail.length > self.aircraftTrailLength)
|
|
|
|
trail.shift();
|
|
|
|
trail.push(newValue);
|
|
|
|
aircraftTrack.setLatLngs(trail);
|
2015-02-13 15:24:41 +00:00
|
|
|
});
|
2015-03-03 12:30:13 +00:00
|
|
|
|
|
|
|
var center = leaflet.latLng(self.latitude(), self.longitude());
|
|
|
|
self.map.setView( center );
|
|
|
|
aircraftMarker.setLatLng(center);
|
2015-01-25 12:02:20 +00:00
|
|
|
}
|
|
|
|
|
2015-03-10 20:48:11 +00:00
|
|
|
ViewModel.prototype.dispose = function() {
|
|
|
|
this.map.remove();
|
|
|
|
}
|
|
|
|
|
2015-02-13 15:24:41 +00:00
|
|
|
// Return component definition
|
|
|
|
return {
|
|
|
|
viewModel : {
|
|
|
|
createViewModel : function(params, componentInfo) {
|
|
|
|
return new ViewModel(params, componentInfo);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
template : htmlString,
|
|
|
|
};
|
2015-01-25 12:02:20 +00:00
|
|
|
});
|