Add aircraft type classification with distinct icons

- Commercial aircraft: Green airplane icon (default)
- Cargo aircraft: Orange box icon (UPS, FedEx, etc.)
- Military aircraft: Red fighter-style icon (RCH, CNV, etc.)
- General aviation: Yellow light aircraft icon
- Ground aircraft: Gray circle with 'G' indicator
- Add visual legend on map showing aircraft type colors
- Aircraft type detection based on flight number patterns

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2025-08-23 22:48:20 +02:00
commit b6a699c24b
3 changed files with 121 additions and 4 deletions

View file

@ -124,6 +124,45 @@ body {
background: #404040; background: #404040;
} }
.legend {
position: absolute;
bottom: 10px;
left: 10px;
background: rgba(45, 45, 45, 0.95);
border: 1px solid #404040;
border-radius: 8px;
padding: 1rem;
z-index: 1000;
min-width: 150px;
}
.legend h4 {
margin: 0 0 0.5rem 0;
font-size: 0.9rem;
color: #ffffff;
}
.legend-item {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.25rem;
font-size: 0.8rem;
}
.legend-icon {
width: 16px;
height: 16px;
border-radius: 2px;
border: 1px solid #ffffff;
}
.legend-icon.commercial { background: #00ff88; }
.legend-icon.cargo { background: #ff8c00; }
.legend-icon.military { background: #ff4444; }
.legend-icon.ga { background: #ffff00; }
.legend-icon.ground { background: #888888; }
.table-controls { .table-controls {
display: flex; display: flex;
gap: 1rem; gap: 1rem;

View file

@ -31,6 +31,30 @@
<button id="center-map">Center Map</button> <button id="center-map">Center Map</button>
<button id="toggle-trails">Toggle Trails</button> <button id="toggle-trails">Toggle Trails</button>
</div> </div>
<div class="legend">
<h4>Aircraft Types</h4>
<div class="legend-item">
<span class="legend-icon commercial"></span>
<span>Commercial</span>
</div>
<div class="legend-item">
<span class="legend-icon cargo"></span>
<span>Cargo</span>
</div>
<div class="legend-item">
<span class="legend-icon military"></span>
<span>Military</span>
</div>
<div class="legend-item">
<span class="legend-icon ga"></span>
<span>General Aviation</span>
</div>
<div class="legend-item">
<span class="legend-icon ground"></span>
<span>Ground</span>
</div>
</div>
</div> </div>
<div id="table-view" class="view"> <div id="table-view" class="view">

View file

@ -243,16 +243,70 @@ class SkyView {
return marker; return marker;
} }
getAircraftType(aircraft) {
if (aircraft.on_ground) return 'ground';
// Determine type based on flight number patterns and characteristics
const flight = aircraft.flight || '';
// Cargo airlines (simplified patterns)
if (/^(UPS|FDX|FX|ABX|ATN|5Y|QY)/i.test(flight)) return 'cargo';
// Military patterns (basic)
if (/^(RCH|CNV|MAC|EVAC|ARMY|NAVY|AF|USAF)/i.test(flight)) return 'military';
// General aviation (no airline code pattern)
if (flight.length > 0 && !/^[A-Z]{2,3}[0-9]/.test(flight)) return 'ga';
// Default commercial
return 'commercial';
}
getAircraftIcon(aircraft) { getAircraftIcon(aircraft) {
const rotation = aircraft.track || 0; const rotation = aircraft.track || 0;
const hasPosition = aircraft.lat && aircraft.lon; const hasPosition = aircraft.lat && aircraft.lon;
const color = hasPosition ? "#00ff88" : "#888888"; const type = this.getAircraftType(aircraft);
const size = hasPosition ? 24 : 18; const size = hasPosition ? 24 : 18;
let color, icon;
switch (type) {
case 'cargo':
color = hasPosition ? "#ff8c00" : "#666666";
icon = `<rect x="8" y="6" width="8" height="12" fill="${color}" stroke="#ffffff" stroke-width="2"/>
<polygon points="12,2 10,6 14,6" fill="${color}" stroke="#ffffff" stroke-width="1"/>
<polygon points="4,10 8,8 8,14" fill="${color}" stroke="#ffffff" stroke-width="1"/>
<polygon points="20,10 16,8 16,14" fill="${color}" stroke="#ffffff" stroke-width="1"/>`;
break;
case 'military':
color = hasPosition ? "#ff4444" : "#666666";
icon = `<polygon points="12,2 9,20 12,18 15,20" fill="${color}" stroke="#ffffff" stroke-width="2"/>
<polygon points="6,8 12,6 12,10" fill="${color}" stroke="#ffffff" stroke-width="1"/>
<polygon points="18,8 12,6 12,10" fill="${color}" stroke="#ffffff" stroke-width="1"/>
<polygon points="8,16 12,14 12,18" fill="${color}" stroke="#ffffff" stroke-width="1"/>
<polygon points="16,16 12,14 12,18" fill="${color}" stroke="#ffffff" stroke-width="1"/>`;
break;
case 'ga':
color = hasPosition ? "#ffff00" : "#666666";
icon = `<polygon points="12,2 11,20 12,19 13,20" fill="${color}" stroke="#ffffff" stroke-width="2"/>
<polygon points="7,12 12,10 12,14" fill="${color}" stroke="#ffffff" stroke-width="1"/>
<polygon points="17,12 12,10 12,14" fill="${color}" stroke="#ffffff" stroke-width="1"/>`;
break;
case 'ground':
color = "#888888";
icon = `<circle cx="12" cy="12" r="6" fill="${color}" stroke="#ffffff" stroke-width="2"/>
<text x="12" y="16" text-anchor="middle" font-size="8" fill="#ffffff">G</text>`;
break;
default: // commercial
color = hasPosition ? "#00ff88" : "#666666";
icon = `<polygon points="12,2 10,20 12,18 14,20" fill="${color}" stroke="#ffffff" stroke-width="2"/>
<polygon points="5,10 12,8 12,12" fill="${color}" stroke="#ffffff" stroke-width="1"/>
<polygon points="19,10 12,8 12,12" fill="${color}" stroke="#ffffff" stroke-width="1"/>`;
break;
}
return `<svg width="${size}" height="${size}" viewBox="0 0 24 24" style="transform: rotate(${rotation}deg); filter: drop-shadow(0 0 3px rgba(0,0,0,0.8));"> return `<svg width="${size}" height="${size}" viewBox="0 0 24 24" style="transform: rotate(${rotation}deg); filter: drop-shadow(0 0 3px rgba(0,0,0,0.8));">
<polygon points="12,2 10,20 12,18 14,20" fill="${color}" stroke="#ffffff" stroke-width="2"/> ${icon}
<polygon points="5,10 12,8 12,12" fill="${color}" stroke="#ffffff" stroke-width="1"/>
<polygon points="19,10 12,8 12,12" fill="${color}" stroke="#ffffff" stroke-width="1"/>
</svg>`; </svg>`;
} }