[feat](trx-frontend): show animated radio path on APRS station click
Draw a blue dashed polyline from the receiver to the clicked APRS station on popup open; remove it on popup close. CSS stroke-dashoffset animation creates a traveling-dash effect suggesting signal propagation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -2367,6 +2367,7 @@ window.addEventListener("resize", resizeHeaderSignalCanvas);
|
|||||||
let aprsMap = null;
|
let aprsMap = null;
|
||||||
let aprsMapBaseLayer = null;
|
let aprsMapBaseLayer = null;
|
||||||
let aprsMapReceiverMarker = null;
|
let aprsMapReceiverMarker = null;
|
||||||
|
let aprsRadioPath = null;
|
||||||
const stationMarkers = new Map();
|
const stationMarkers = new Map();
|
||||||
const locatorMarkers = new Map();
|
const locatorMarkers = new Map();
|
||||||
const mapMarkers = new Set();
|
const mapMarkers = new Set();
|
||||||
@@ -2423,13 +2424,25 @@ function initAprsMap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rebuild APRS popup content on open so age and distance are always fresh
|
// Rebuild APRS popup content on open so age and distance are always fresh
|
||||||
|
// and draw an animated radio path from receiver to the station
|
||||||
aprsMap.on("popupopen", function(e) {
|
aprsMap.on("popupopen", function(e) {
|
||||||
const marker = e.popup._source;
|
const marker = e.popup._source;
|
||||||
|
if (aprsRadioPath) { aprsRadioPath.remove(); aprsRadioPath = null; }
|
||||||
if (!marker || !marker._aprsCall) return;
|
if (!marker || !marker._aprsCall) return;
|
||||||
const entry = stationMarkers.get(marker._aprsCall);
|
const entry = stationMarkers.get(marker._aprsCall);
|
||||||
if (!entry) return;
|
if (!entry) return;
|
||||||
const ll = marker.getLatLng();
|
const ll = marker.getLatLng();
|
||||||
e.popup.setContent(buildAprsPopupHtml(marker._aprsCall, ll.lat, ll.lng, entry.info || "", entry.pkt));
|
e.popup.setContent(buildAprsPopupHtml(marker._aprsCall, ll.lat, ll.lng, entry.info || "", entry.pkt));
|
||||||
|
if (serverLat != null && serverLon != null) {
|
||||||
|
aprsRadioPath = L.polyline(
|
||||||
|
[[serverLat, serverLon], [ll.lat, ll.lng]],
|
||||||
|
{ className: "aprs-radio-path", color: "#3388ff", weight: 2, opacity: 0.85, interactive: false }
|
||||||
|
).addTo(aprsMap);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
aprsMap.on("popupclose", function() {
|
||||||
|
if (aprsRadioPath) { aprsRadioPath.remove(); aprsRadioPath = null; }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Materialise any stations that were buffered before the map was ready
|
// Materialise any stations that were buffered before the map was ready
|
||||||
|
|||||||
@@ -1082,6 +1082,8 @@ small { color: var(--text-muted); }
|
|||||||
.aprs-popup-table td { padding: 0.06rem 0.3rem 0.06rem 0; vertical-align: top; font-size: 0.88em; }
|
.aprs-popup-table td { padding: 0.06rem 0.3rem 0.06rem 0; vertical-align: top; font-size: 0.88em; }
|
||||||
.aprs-popup-label { color: var(--text-muted); white-space: nowrap; padding-right: 0.5rem !important; }
|
.aprs-popup-label { color: var(--text-muted); white-space: nowrap; padding-right: 0.5rem !important; }
|
||||||
.aprs-popup-info { font-size: 0.85em; color: var(--text); border-top: 1px solid var(--border-light); padding-top: 0.25rem; margin-top: 0.1rem; word-break: break-word; }
|
.aprs-popup-info { font-size: 0.85em; color: var(--text); border-top: 1px solid var(--border-light); padding-top: 0.25rem; margin-top: 0.1rem; word-break: break-word; }
|
||||||
|
.aprs-radio-path { stroke-dasharray: 10 5 !important; animation: aprs-radio-path-flow 0.7s linear infinite; }
|
||||||
|
@keyframes aprs-radio-path-flow { to { stroke-dashoffset: -15; } }
|
||||||
.aprs-bar-pos { background: none; border: none; padding: 0; margin-left: 0.4em; font-family: inherit; font-size: inherit; color: var(--accent-green); cursor: pointer; }
|
.aprs-bar-pos { background: none; border: none; padding: 0; margin-left: 0.4em; font-family: inherit; font-size: inherit; color: var(--accent-green); cursor: pointer; }
|
||||||
.aprs-bar-pos:hover { text-decoration: underline; }
|
.aprs-bar-pos:hover { text-decoration: underline; }
|
||||||
.aprs-byte { color: var(--accent-yellow); background: rgba(255, 214, 0, 0.12); border: 1px solid rgba(255, 214, 0, 0.25); border-radius: 4px; padding: 0 0.2rem; margin: 0 0.1rem; font-size: 0.78em; }
|
.aprs-byte { color: var(--accent-yellow); background: rgba(255, 214, 0, 0.12); border: 1px solid rgba(255, 214, 0, 0.25); border-radius: 4px; padding: 0 0.2rem; margin: 0 0.1rem; font-size: 0.78em; }
|
||||||
|
|||||||
Reference in New Issue
Block a user