Show altitude colors in plane track lines
Show altitude color key on map Correctly handle retina images with CSS
BIN
public_html/images/altitude_legend.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
public_html/images/altitude_legend@2x.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
public_html/images/altitude_legend@3x.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
public_html/images/box-checked@2x.png
Normal file
After Width: | Height: | Size: 292 B |
BIN
public_html/images/box-checked@3x.png
Normal file
After Width: | Height: | Size: 325 B |
BIN
public_html/images/box-empty@2x.png
Normal file
After Width: | Height: | Size: 232 B |
BIN
public_html/images/box-empty@3x.png
Normal file
After Width: | Height: | Size: 281 B |
|
@ -248,6 +248,9 @@
|
||||||
<div id="expand_sidebar_control" class="ol-unselectable ol-control">
|
<div id="expand_sidebar_control" class="ol-unselectable ol-control">
|
||||||
<button id="expand_sidebar_button" title="Expand Sidebar"></button>
|
<button id="expand_sidebar_button" title="Expand Sidebar"></button>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="altitude_chart" class="ol-unselectable ol-control">
|
||||||
|
<button id="altitude_chart_button"></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar_container">
|
<div id="sidebar_container">
|
||||||
<div id="splitter" class="ui-resizable-handle ui-resizable-w"></div>
|
<div id="splitter" class="ui-resizable-handle ui-resizable-w"></div>
|
||||||
|
|
|
@ -115,7 +115,8 @@ PlaneObject.prototype.updateTrack = function(estimate_time) {
|
||||||
head_update: this.last_position_time,
|
head_update: this.last_position_time,
|
||||||
tail_update: this.last_position_time,
|
tail_update: this.last_position_time,
|
||||||
estimated: false,
|
estimated: false,
|
||||||
ground: (this.altitude === "ground")
|
ground: (this.altitude === "ground"),
|
||||||
|
altitude: this.altitude
|
||||||
};
|
};
|
||||||
this.track_linesegs.push(newseg);
|
this.track_linesegs.push(newseg);
|
||||||
this.history_size ++;
|
this.history_size ++;
|
||||||
|
@ -176,6 +177,7 @@ PlaneObject.prototype.updateTrack = function(estimate_time) {
|
||||||
head_update: this.last_position_time,
|
head_update: this.last_position_time,
|
||||||
tail_update: this.last_position_time,
|
tail_update: this.last_position_time,
|
||||||
estimated: false,
|
estimated: false,
|
||||||
|
altitude: this.altitude,
|
||||||
ground: (this.altitude === "ground") });
|
ground: (this.altitude === "ground") });
|
||||||
this.history_size += 3;
|
this.history_size += 3;
|
||||||
return true;
|
return true;
|
||||||
|
@ -236,33 +238,11 @@ PlaneObject.prototype.getMarkerColor = function() {
|
||||||
|
|
||||||
var h, s, l;
|
var h, s, l;
|
||||||
|
|
||||||
if (this.altitude === null) {
|
var colorArr = this.getAltitudeColor();
|
||||||
h = ColorByAlt.unknown.h;
|
|
||||||
s = ColorByAlt.unknown.s;
|
|
||||||
l = ColorByAlt.unknown.l;
|
|
||||||
} else if (this.altitude === "ground") {
|
|
||||||
h = ColorByAlt.ground.h;
|
|
||||||
s = ColorByAlt.ground.s;
|
|
||||||
l = ColorByAlt.ground.l;
|
|
||||||
} else {
|
|
||||||
s = ColorByAlt.air.s;
|
|
||||||
l = ColorByAlt.air.l;
|
|
||||||
|
|
||||||
// find the pair of points the current altitude lies between,
|
h = colorArr[0];
|
||||||
// and interpolate the hue between those points
|
s = colorArr[1];
|
||||||
var hpoints = ColorByAlt.air.h;
|
l = colorArr[2];
|
||||||
h = hpoints[0].val;
|
|
||||||
for (var i = hpoints.length-1; i >= 0; --i) {
|
|
||||||
if (this.altitude > hpoints[i].alt) {
|
|
||||||
if (i == hpoints.length-1) {
|
|
||||||
h = hpoints[i].val;
|
|
||||||
} else {
|
|
||||||
h = hpoints[i].val + (hpoints[i+1].val - hpoints[i].val) * (this.altitude - hpoints[i].alt) / (hpoints[i+1].alt - hpoints[i].alt)
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have not seen a recent position update, change color
|
// If we have not seen a recent position update, change color
|
||||||
if (this.seen_pos > 15) {
|
if (this.seen_pos > 15) {
|
||||||
|
@ -300,6 +280,56 @@ PlaneObject.prototype.getMarkerColor = function() {
|
||||||
return 'hsl(' + (h/5).toFixed(0)*5 + ',' + (s/5).toFixed(0)*5 + '%,' + (l/5).toFixed(0)*5 + '%)'
|
return 'hsl(' + (h/5).toFixed(0)*5 + ',' + (s/5).toFixed(0)*5 + '%,' + (l/5).toFixed(0)*5 + '%)'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlaneObject.prototype.getAltitudeColor = function(altitude) {
|
||||||
|
var h, s, l;
|
||||||
|
|
||||||
|
if (typeof altitude === 'undefined') {
|
||||||
|
altitude = this.altitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (altitude === null) {
|
||||||
|
h = ColorByAlt.unknown.h;
|
||||||
|
s = ColorByAlt.unknown.s;
|
||||||
|
l = ColorByAlt.unknown.l;
|
||||||
|
} else if (this.altitude === "ground") {
|
||||||
|
h = ColorByAlt.ground.h;
|
||||||
|
s = ColorByAlt.ground.s;
|
||||||
|
l = ColorByAlt.ground.l;
|
||||||
|
} else {
|
||||||
|
s = ColorByAlt.air.s;
|
||||||
|
l = ColorByAlt.air.l;
|
||||||
|
|
||||||
|
// find the pair of points the current altitude lies between,
|
||||||
|
// and interpolate the hue between those points
|
||||||
|
var hpoints = ColorByAlt.air.h;
|
||||||
|
h = hpoints[0].val;
|
||||||
|
for (var i = hpoints.length-1; i >= 0; --i) {
|
||||||
|
if (altitude > hpoints[i].alt) {
|
||||||
|
if (i == hpoints.length-1) {
|
||||||
|
h = hpoints[i].val;
|
||||||
|
} else {
|
||||||
|
h = hpoints[i].val + (hpoints[i+1].val - hpoints[i].val) * (altitude - hpoints[i].alt) / (hpoints[i+1].alt - hpoints[i].alt)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h < 0) {
|
||||||
|
h = (h % 360) + 360;
|
||||||
|
} else if (h >= 360) {
|
||||||
|
h = h % 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s < 5) s = 5;
|
||||||
|
else if (s > 95) s = 95;
|
||||||
|
|
||||||
|
if (l < 5) l = 5;
|
||||||
|
else if (l > 95) l = 95;
|
||||||
|
|
||||||
|
return [h, s, l];
|
||||||
|
}
|
||||||
|
|
||||||
PlaneObject.prototype.updateIcon = function() {
|
PlaneObject.prototype.updateIcon = function() {
|
||||||
var scaleFactor = Math.max(0.2, Math.min(1.2, 0.15 * Math.pow(1.25, ZoomLvl))).toFixed(1);
|
var scaleFactor = Math.max(0.2, Math.min(1.2, 0.15 * Math.pow(1.25, ZoomLvl))).toFixed(1);
|
||||||
|
|
||||||
|
@ -500,6 +530,18 @@ PlaneObject.prototype.updateMarker = function(moved) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// return the styling of the lines based on altitude
|
||||||
|
PlaneObject.prototype.altitudeLines = function(altitude) {
|
||||||
|
var colorArr = this.getAltitudeColor(altitude);
|
||||||
|
return new ol.style.Style({
|
||||||
|
stroke: new ol.style.Stroke({
|
||||||
|
color: 'hsl(' + (colorArr[0]/5).toFixed(0)*5 + ',' + (colorArr[1]/5).toFixed(0)*5 + '%,' + (colorArr[2]/5).toFixed(0)*5 + '%)',
|
||||||
|
width: 2
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Update our planes tail line,
|
// Update our planes tail line,
|
||||||
PlaneObject.prototype.updateLines = function() {
|
PlaneObject.prototype.updateLines = function() {
|
||||||
if (!this.selected)
|
if (!this.selected)
|
||||||
|
@ -542,7 +584,7 @@ PlaneObject.prototype.updateLines = function() {
|
||||||
var lastfixed = lastseg.fixed.getCoordinateAt(1.0);
|
var lastfixed = lastseg.fixed.getCoordinateAt(1.0);
|
||||||
var geom = new ol.geom.LineString([lastfixed, ol.proj.fromLonLat(this.position)]);
|
var geom = new ol.geom.LineString([lastfixed, ol.proj.fromLonLat(this.position)]);
|
||||||
this.elastic_feature = new ol.Feature(geom);
|
this.elastic_feature = new ol.Feature(geom);
|
||||||
this.elastic_feature.setStyle(this.altitude === 'ground' ? groundStyle : airStyle);
|
this.elastic_feature.setStyle(this.altitudeLines(this.altitude));
|
||||||
|
|
||||||
if (oldElastic < 0) {
|
if (oldElastic < 0) {
|
||||||
PlaneTrailFeatures.push(this.elastic_feature);
|
PlaneTrailFeatures.push(this.elastic_feature);
|
||||||
|
@ -557,10 +599,8 @@ PlaneObject.prototype.updateLines = function() {
|
||||||
seg.feature = new ol.Feature(seg.fixed);
|
seg.feature = new ol.Feature(seg.fixed);
|
||||||
if (seg.estimated) {
|
if (seg.estimated) {
|
||||||
seg.feature.setStyle(estimateStyle);
|
seg.feature.setStyle(estimateStyle);
|
||||||
} else if (seg.ground) {
|
|
||||||
seg.feature.setStyle(groundStyle);
|
|
||||||
} else {
|
} else {
|
||||||
seg.feature.setStyle(airStyle);
|
seg.feature.setStyle(this.altitudeLines(seg.altitude));
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaneTrailFeatures.push(seg.feature);
|
PlaneTrailFeatures.push(seg.feature);
|
||||||
|
|
|
@ -520,7 +520,7 @@ function initialize_map() {
|
||||||
}),
|
}),
|
||||||
controls: [new ol.control.Zoom(),
|
controls: [new ol.control.Zoom(),
|
||||||
new ol.control.Rotate(),
|
new ol.control.Rotate(),
|
||||||
new ol.control.Attribution({collapsed: false}),
|
new ol.control.Attribution({collapsed: true}),
|
||||||
new ol.control.ScaleLine({units: DisplayUnits}),
|
new ol.control.ScaleLine({units: DisplayUnits}),
|
||||||
new ol.control.LayerSwitcher()
|
new ol.control.LayerSwitcher()
|
||||||
],
|
],
|
||||||
|
|
|
@ -53,34 +53,10 @@ html, body {
|
||||||
|
|
||||||
#toggle_sidebar_button.show_sidebar {
|
#toggle_sidebar_button.show_sidebar {
|
||||||
background-image: url("images/table-icon.png");
|
background-image: url("images/table-icon.png");
|
||||||
background-image:
|
|
||||||
-webkit-image-set(
|
|
||||||
"images/table-icon.png" 1x,
|
|
||||||
"images/table-icon@2x.png" 2x,
|
|
||||||
"images/table-icon@3x.png" 3x
|
|
||||||
);
|
|
||||||
background-image:
|
|
||||||
-image-set(
|
|
||||||
"images/table-icon.png" 1x,
|
|
||||||
"images/table-icon@2x.png" 2x,
|
|
||||||
"images/table-icon@3x.png" 3x
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#toggle_sidebar_button.hide_sidebar {
|
#toggle_sidebar_button.hide_sidebar {
|
||||||
background-image: url("images/map-icon.png");
|
background-image: url("images/map-icon.png");
|
||||||
background-image:
|
|
||||||
-webkit-image-set(
|
|
||||||
"images/map-icon.png" 1x,
|
|
||||||
"images/map-icon@2x.png" 2x,
|
|
||||||
"images/map-icon@3x.png" 3x
|
|
||||||
);
|
|
||||||
background-image:
|
|
||||||
-image-set(
|
|
||||||
"images/map-icon.png" 1x,
|
|
||||||
"images/map-icon@2x.png" 2x,
|
|
||||||
"images/map-icon@3x.png" 3x
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#expand_sidebar_control {
|
#expand_sidebar_control {
|
||||||
|
@ -104,18 +80,6 @@ html, body {
|
||||||
|
|
||||||
#expand_sidebar_button {
|
#expand_sidebar_button {
|
||||||
background-image: url("images/table-icon.png");
|
background-image: url("images/table-icon.png");
|
||||||
background-image:
|
|
||||||
-webkit-image-set(
|
|
||||||
"images/table-icon.png" 1x,
|
|
||||||
"images/table-icon@2x.png" 2x,
|
|
||||||
"images/table-icon@3x.png" 3x
|
|
||||||
);
|
|
||||||
background-image:
|
|
||||||
-image-set(
|
|
||||||
"images/table-icon.png" 1x,
|
|
||||||
"images/table-icon@2x.png" 2x,
|
|
||||||
"images/table-icon@3x.png" 3x
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar_container {
|
#sidebar_container {
|
||||||
|
@ -140,34 +104,10 @@ html, body {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
background-image: url("images/column-adjust.png");
|
background-image: url("images/column-adjust.png");
|
||||||
background-image:
|
|
||||||
-webkit-image-set(
|
|
||||||
"images/column-adjust.png" 1x,
|
|
||||||
"images/column-adjust@2x.png" 2x,
|
|
||||||
"images/column-adjust@3x.png" 3x
|
|
||||||
);
|
|
||||||
background-image:
|
|
||||||
-image-set(
|
|
||||||
"images/column-adjust.png" 1x,
|
|
||||||
"images/column-adjust@2x.png" 2x,
|
|
||||||
"images/column-adjust@3x.png" 3x
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ol-zoom-in {
|
.ol-zoom-in {
|
||||||
background-image: url("images/zoom-in.png");
|
background-image: url("images/zoom-in.png");
|
||||||
background-image:
|
|
||||||
-webkit-image-set(
|
|
||||||
"images/zoom-in.png" 1x,
|
|
||||||
"images/zoom-in@2x.png" 2x,
|
|
||||||
"images/zoom-in@3x.png" 3x
|
|
||||||
);
|
|
||||||
background-image:
|
|
||||||
-image-set(
|
|
||||||
"images/zoom-in.png" 1x,
|
|
||||||
"images/zoom-in@2x.png" 2x,
|
|
||||||
"images/zoom-in@3x.png" 3x
|
|
||||||
);
|
|
||||||
color:transparent !important;
|
color:transparent !important;
|
||||||
width: 19px !important;
|
width: 19px !important;
|
||||||
height: 19px !important;
|
height: 19px !important;
|
||||||
|
@ -177,18 +117,6 @@ html, body {
|
||||||
|
|
||||||
.ol-zoom-out {
|
.ol-zoom-out {
|
||||||
background-image: url("images/zoom-out.png");
|
background-image: url("images/zoom-out.png");
|
||||||
background-image:
|
|
||||||
-webkit-image-set(
|
|
||||||
"images/zoom-out.png" 1x,
|
|
||||||
"images/zoom-out@2x.png" 2x,
|
|
||||||
"images/zoom-out@3x.png" 3x
|
|
||||||
);
|
|
||||||
background-image:
|
|
||||||
-image-set(
|
|
||||||
"images/zoom-out.png" 1x,
|
|
||||||
"images/zoom-out@2x.png" 2x,
|
|
||||||
"images/zoom-out@3x.png" 3x
|
|
||||||
);
|
|
||||||
color:transparent !important;
|
color:transparent !important;
|
||||||
width: 19px !important;
|
width: 19px !important;
|
||||||
height: 19px !important;
|
height: 19px !important;
|
||||||
|
@ -668,3 +596,81 @@ select.error, textarea.error, input.error {
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#altitude_chart {
|
||||||
|
float: right;
|
||||||
|
width: 502px;
|
||||||
|
height: 18px;
|
||||||
|
right: 40px;
|
||||||
|
bottom: 10px;
|
||||||
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#altitude_chart_button {
|
||||||
|
background-image: url('images/altitude_legend.png');
|
||||||
|
background-color: transparent;
|
||||||
|
width: 502px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retina 2x images */
|
||||||
|
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
|
||||||
|
#altitude_chart_button {
|
||||||
|
background-image: url('images/altitude_legend@2x.png');
|
||||||
|
}
|
||||||
|
.settingsCheckboxChecked {
|
||||||
|
background-image: url('images/box-checked@2x.png') !important;
|
||||||
|
}
|
||||||
|
.settingsCheckbox {
|
||||||
|
background-image: url('images/box-empty@2x.png');
|
||||||
|
}
|
||||||
|
.ol-zoom-out {
|
||||||
|
background-image: url("images/zoom-out@2x.png");
|
||||||
|
}
|
||||||
|
.ol-zoom-in {
|
||||||
|
background-image: url("images/zoom-in@2x.png");
|
||||||
|
}
|
||||||
|
#splitter {
|
||||||
|
background-image: url("images/column-adjust@2x.png");
|
||||||
|
}
|
||||||
|
#toggle_sidebar_button.show_sidebar {
|
||||||
|
background-image: url("images/table-icon@2x.png");
|
||||||
|
}
|
||||||
|
#expand_sidebar_button {
|
||||||
|
background-image: url("images/table-icon@2x.png");
|
||||||
|
}
|
||||||
|
#toggle_sidebar_button.hide_sidebar {
|
||||||
|
background-image: url("images/map-icon@2x.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retina 3x images */
|
||||||
|
@media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 192dpi) {
|
||||||
|
#altitude_chart_button {
|
||||||
|
background-image: url('images/altitude_legend@3x.png');
|
||||||
|
}
|
||||||
|
.settingsCheckboxChecked {
|
||||||
|
background-image: url('images/box-checked@3x.png') !important;
|
||||||
|
}
|
||||||
|
.settingsCheckbox {
|
||||||
|
background-image: url('images/box-empty@3x.png');
|
||||||
|
}
|
||||||
|
.ol-zoom-out {
|
||||||
|
background-image: url("images/zoom-out@3x.png");
|
||||||
|
}
|
||||||
|
.ol-zoom-in {
|
||||||
|
background-image: url("images/zoom-in@3x.png");
|
||||||
|
}
|
||||||
|
#splitter {
|
||||||
|
background-image: url("images/column-adjust@3x.png");
|
||||||
|
}
|
||||||
|
#toggle_sidebar_button.show_sidebar {
|
||||||
|
background-image: url("images/table-icon@3x.png");
|
||||||
|
}
|
||||||
|
#expand_sidebar_button {
|
||||||
|
background-image: url("images/table-icon@3x.png");
|
||||||
|
}
|
||||||
|
#toggle_sidebar_button.hide_sidebar {
|
||||||
|
background-image: url("images/map-icon@3x.png");
|
||||||
|
}
|
||||||
|
}
|