Files
DroneMapUK/index.html

192 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>DroneMapUK — UK Airspace</title>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.css">
<script src="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="map"></div>
<!-- API key setup modal -->
<div id="key-modal">
<div class="modal-box">
<h2>MapTiler API Key</h2>
<p>Get a free key at <a href="https://maptiler.com" target="_blank" rel="noopener">maptiler.com</a> then paste it below.</p>
<input id="key-input" type="text" placeholder="Your MapTiler API key" autocomplete="off" spellcheck="false">
<button id="key-submit">Load Map</button>
</div>
</div>
<!-- Sidebar panel -->
<div id="panel">
<div id="panel-header">
<span class="panel-title">DroneMapUK</span>
<div class="header-btns">
<button id="warn-btn" title="Planning disclaimer">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
</button>
<button id="panel-toggle" title="Toggle panel"></button>
</div>
</div>
<div id="warn-popup" class="hidden">
Planning aid only. Always check <a href="https://www.aurora.nats.co.uk/" target="_blank" rel="noopener">NOTAMs</a> and official CAA sources before any flight.
</div>
<div id="panel-body">
<!-- ── Airspace restrictions ── -->
<div class="section-label">AIRSPACE</div>
<label class="layer-row">
<input type="checkbox" data-layer="nats" checked>
<span class="dot dot-nats"></span>
<span>NATS AIP Airspace</span>
</label>
<p class="layer-note" id="nats-status">Loading…</p>
<div id="nats-progress" class="progress-bar hidden">
<div id="nats-progress-fill" class="progress-fill"></div>
</div>
<div class="nats-type-grid">
<div class="type-cell"><label class="type-check"><input type="checkbox" data-nats-type="R" checked><span class="tc-r">R</span></label><button class="info-btn" data-info="Restricted Area — access limited by national authority"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></button></div>
<div class="type-cell"><label class="type-check"><input type="checkbox" data-nats-type="P" checked><span class="tc-r">P</span></label><button class="info-btn" data-info="Prohibited Area — flight permanently prohibited"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></button></div>
<div class="type-cell"><label class="type-check"><input type="checkbox" data-nats-type="CTR" checked><span class="tc-ctr">CTR</span></label><button class="info-btn" data-info="Control Zone — controlled airspace immediately around an aerodrome, surface to upper limit"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></button></div>
<div class="type-cell"><label class="type-check"><input type="checkbox" data-nats-type="CTA" checked><span class="tc-cta">CTA</span></label><button class="info-btn" data-info="Control Area — larger block of controlled airspace above a minimum altitude"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></button></div>
<div class="type-cell"><label class="type-check"><input type="checkbox" data-nats-type="TMA" checked><span class="tc-cta">TMA</span></label><button class="info-btn" data-info="Terminal Manoeuvring Area — controlled airspace around a busy airport or cluster of airports"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></button></div>
<div class="type-cell"><label class="type-check"><input type="checkbox" data-nats-type="RAS" checked><span class="tc-ras">RAS</span></label><button class="info-btn" data-info="Radar Advisory Service — ATC provides traffic information and avoidance advice on request"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></button></div>
<div class="type-cell"><label class="type-check"><input type="checkbox" data-nats-type="OTHER:TMZ" checked><span class="tc-tmz">TMZ</span></label><button class="info-btn" data-info="Transponder Mandatory Zone — Mode C or S transponder required when flying inside"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></button></div>
</div>
<div id="nats-type-info" class="type-info-box hidden"></div>
<label class="layer-row">
<input type="checkbox" data-layer="frz" checked>
<span class="dot dot-frz"></span>
<span>Flight Restriction Zones</span>
</label>
<p class="layer-note">5 km radius around licensed aerodromes (approx.)</p>
<div class="layer-row-outer">
<label class="layer-row">
<input type="checkbox" data-layer="danger" checked>
<span class="dot dot-danger"></span>
<span>Danger / Restricted Areas</span>
</label>
<button class="info-btn" data-info="No built-in data — upload a GeoJSON file via Load Data below. Each upload replaces the previous data." data-infobox="layer-override-info"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></button>
</div>
<div class="layer-row-outer">
<label class="layer-row">
<input type="checkbox" data-layer="military" checked>
<span class="dot dot-military"></span>
<span>MoD / Military Areas</span>
</label>
<button class="info-btn" data-info="No built-in data — upload a GeoJSON file via Load Data below. Each upload replaces the previous data." data-infobox="layer-override-info"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></button>
</div>
<div id="layer-override-info" class="type-info-box hidden"></div>
<!-- ── Protected nature ── -->
<div class="section-label" style="margin-top:12px">PROTECTED AREAS</div>
<label class="layer-row">
<input type="checkbox" data-layer="national-parks" checked>
<span class="dot dot-parks"></span>
<span>National Parks (GB)</span>
</label>
<label class="layer-row">
<input type="checkbox" data-layer="royal-parks" checked>
<span class="dot dot-royal"></span>
<span>Royal Parks (London)</span>
</label>
<label class="layer-row">
<input type="checkbox" data-layer="sssi" checked>
<span class="dot dot-sssi"></span>
<span>SSSIs</span>
</label>
<p class="layer-note" id="sssi-status">England: auto-loaded at zoom ≥ 8 · Scotland/Wales: load file</p>
<!-- ── Managed land ── -->
<div class="section-label" style="margin-top:12px">MANAGED LAND</div>
<label class="layer-row">
<input type="checkbox" data-layer="forestry">
<span class="dot dot-forestry"></span>
<span>Forestry managed land</span>
</label>
<p class="layer-note">Forestry England / FLS / NRW — load GeoJSON below</p>
<div class="type-all-row">
<button class="type-all-btn" id="layers-select-all">Select all</button>
<button class="type-all-btn" id="layers-deselect-all">Deselect all</button>
</div>
<!-- ── Location ── -->
<div class="section-label" style="margin-top:12px">LOCATION</div>
<button id="locate-btn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3"/>
<circle cx="12" cy="12" r="9" stroke-dasharray="3 3" opacity=".4"/>
</svg>
<span id="locate-label">Track location</span>
</button>
<!-- ── Map style ── -->
<div class="section-label" style="margin-top:12px">MAP STYLE</div>
<div class="style-row">
<button class="style-btn active" data-style="outdoor">Terrain</button>
<button class="style-btn" data-style="satellite">Satellite</button>
<button class="style-btn" data-style="hybrid">Hybrid</button>
<button class="style-btn" data-style="streets">Streets</button>
</div>
<div class="toggle-row">
<span>3D Terrain</span>
<label class="switch" title="Toggle 3D terrain">
<input type="checkbox" id="toggle-3d">
<span class="switch-track"><span class="switch-thumb"></span></span>
</label>
</div>
<div class="toggle-row">
<span>Hillshade <span class="hint">(best on Satellite)</span></span>
<label class="switch" title="Toggle hillshade terrain overlay">
<input type="checkbox" id="toggle-hillshade">
<span class="switch-track"><span class="switch-thumb"></span></span>
</label>
</div>
<!-- ── Load data ── -->
<div class="section-label" style="margin-top:12px">LOAD DATA</div>
<select id="layer-select" class="layer-select">
<option value="danger">Danger / Restricted</option>
<option value="military">Military Areas</option>
<option value="forestry">Forestry managed land</option>
<option value="sssi">SSSIs (Scotland / Wales)</option>
</select>
<button class="load-btn load-btn-full" id="geojson-btn">Load GeoJSON…</button>
<input type="file" id="geojson-file" accept=".geojson,.json" style="display:none">
<div class="data-links">
<a href="https://www.aurora.nats.co.uk/" target="_blank" rel="noopener">NOTAMs</a> ·
<a href="https://nats-uk.ead-it.com/cms-nats/opencms/en/uas-restriction-zones/" target="_blank" rel="noopener">NATS UAS Zones</a> ·
<a href="https://data-forestry.opendata.arcgis.com/" target="_blank" rel="noopener">Forestry England</a> ·
<a href="https://www.arcgis.com/apps/webappviewer/index.html?id=e4b9f5f437474e0481a3cec097e4c2ec" target="_blank" rel="noopener">FLS Scotland</a> ·
<a href="https://datamap.gov.wales/" target="_blank" rel="noopener">NRW Wales</a> ·
<a href="https://naturalengland-defra.opendata.arcgis.com/" target="_blank" rel="noopener">Natural England</a>
</div>
</div>
</div>
<!-- Click info popup -->
<div id="popup" class="hidden">
<button id="popup-close"></button>
<div id="popup-body"></div>
</div>
<script src="app.js"></script>
</body>
</html>