[feat](trx-frontend-http): color radio paths by band or mode
Radio paths and decode contact paths now use the same color as the marker they belong to, respecting the active filter mode: - Band mode: color follows the band (golden-angle HSL hue) - Mode/source mode: color follows the source type (FT8/WSPR/bookmark) APRS, AIS, and VDES paths use their fixed source colors unchanged. Decode contact paths sync color when the filter mode is switched. CSS stroke/stroke-opacity removed from path classes so Leaflet's color option takes effect; dasharray and flow animation are retained. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -4035,6 +4035,11 @@ function syncLocatorMarkerStyles() {
|
|||||||
if (!entry?.marker) continue;
|
if (!entry?.marker) continue;
|
||||||
entry.marker.setStyle(locatorStyleForEntry(entry, locatorEntryCount(entry)));
|
entry.marker.setStyle(locatorStyleForEntry(entry, locatorEntryCount(entry)));
|
||||||
}
|
}
|
||||||
|
for (const entry of decodeContactPaths.values()) {
|
||||||
|
if (!entry?.line) continue;
|
||||||
|
const color = decodeContactPathColor(entry);
|
||||||
|
entry.line.setStyle({ color, opacity: 0.78 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopSelectedLocatorPulse() {
|
function stopSelectedLocatorPulse() {
|
||||||
@@ -4118,20 +4123,30 @@ function midpointLatLon(a, b) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function decodeContactPathColor(entry) {
|
||||||
|
const srcEntry = locatorMarkers.get(entry?.sourceGrid);
|
||||||
|
if (srcEntry) return locatorStyleForEntry(srcEntry, locatorEntryCount(srcEntry)).color;
|
||||||
|
return locatorFilterColor("ft8");
|
||||||
|
}
|
||||||
|
|
||||||
function ensureDecodeContactPathRendered(entry) {
|
function ensureDecodeContactPathRendered(entry) {
|
||||||
if (!entry || !aprsMap) return;
|
if (!entry || !aprsMap) return;
|
||||||
const linePoints = [
|
const linePoints = [
|
||||||
[entry.from.lat, entry.from.lon],
|
[entry.from.lat, entry.from.lon],
|
||||||
[entry.to.lat, entry.to.lon],
|
[entry.to.lat, entry.to.lon],
|
||||||
];
|
];
|
||||||
|
const color = decodeContactPathColor(entry);
|
||||||
if (!entry.line) {
|
if (!entry.line) {
|
||||||
entry.line = L.polyline(linePoints, {
|
entry.line = L.polyline(linePoints, {
|
||||||
|
color,
|
||||||
|
opacity: 0.78,
|
||||||
className: "decode-contact-path",
|
className: "decode-contact-path",
|
||||||
weight: 2.8,
|
weight: 2.8,
|
||||||
interactive: false,
|
interactive: false,
|
||||||
}).addTo(aprsMap);
|
}).addTo(aprsMap);
|
||||||
} else {
|
} else {
|
||||||
entry.line.setLatLngs(linePoints);
|
entry.line.setLatLngs(linePoints);
|
||||||
|
entry.line.setStyle({ color, opacity: 0.78 });
|
||||||
if (!aprsMap.hasLayer(entry.line)) entry.line.addTo(aprsMap);
|
if (!aprsMap.hasLayer(entry.line)) entry.line.addTo(aprsMap);
|
||||||
}
|
}
|
||||||
const mid = midpointLatLon(entry.from, entry.to);
|
const mid = midpointLatLon(entry.from, entry.to);
|
||||||
@@ -4169,14 +4184,14 @@ function syncDecodeContactPathVisibility() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMapRadioPathTo(lat, lon, className = "aprs-radio-path") {
|
function setMapRadioPathTo(lat, lon, color, className = "aprs-radio-path") {
|
||||||
clearMapRadioPath();
|
clearMapRadioPath();
|
||||||
if (!mapP2pRadioPathsEnabled || serverLat == null || serverLon == null || !Number.isFinite(lat) || !Number.isFinite(lon) || !aprsMap) {
|
if (!mapP2pRadioPathsEnabled || serverLat == null || serverLon == null || !Number.isFinite(lat) || !Number.isFinite(lon) || !aprsMap) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
aprsRadioPath = L.polyline(
|
aprsRadioPath = L.polyline(
|
||||||
[[serverLat, serverLon], [lat, lon]],
|
[[serverLat, serverLon], [lat, lon]],
|
||||||
{ className, weight: 2, interactive: false }
|
{ color, opacity: 0.85, weight: 2, interactive: false, className }
|
||||||
).addTo(aprsMap);
|
).addTo(aprsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4763,7 +4778,7 @@ function initAprsMap() {
|
|||||||
entry.track.addTo(aprsMap);
|
entry.track.addTo(aprsMap);
|
||||||
}
|
}
|
||||||
selectedAprsTrackCall = String(marker._aprsCall);
|
selectedAprsTrackCall = String(marker._aprsCall);
|
||||||
setMapRadioPathTo(ll.lat, ll.lng, "aprs-radio-path");
|
setMapRadioPathTo(ll.lat, ll.lng, mapSourceColor("aprs"), "aprs-radio-path");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4775,7 +4790,7 @@ function initAprsMap() {
|
|||||||
ensureAisTrack(String(marker._aisMmsi), entry);
|
ensureAisTrack(String(marker._aisMmsi), entry);
|
||||||
selectedAisTrackMmsi = String(marker._aisMmsi);
|
selectedAisTrackMmsi = String(marker._aisMmsi);
|
||||||
syncSelectedAisTrackVisibility();
|
syncSelectedAisTrackVisibility();
|
||||||
setMapRadioPathTo(ll.lat, ll.lng, "aprs-radio-path");
|
setMapRadioPathTo(ll.lat, ll.lng, mapSourceColor("ais"), "aprs-radio-path");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4784,7 +4799,7 @@ function initAprsMap() {
|
|||||||
const entry = vdesMarkers.get(String(marker._vdesKey));
|
const entry = vdesMarkers.get(String(marker._vdesKey));
|
||||||
if (!entry || !entry.msg) return;
|
if (!entry || !entry.msg) return;
|
||||||
e.popup.setContent(buildVdesPopupHtml(entry.msg));
|
e.popup.setContent(buildVdesPopupHtml(entry.msg));
|
||||||
setMapRadioPathTo(ll.lat, ll.lng, "aprs-radio-path");
|
setMapRadioPathTo(ll.lat, ll.lng, mapSourceColor("vdes"), "aprs-radio-path");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4792,7 +4807,9 @@ function initAprsMap() {
|
|||||||
const center = locatorMarkerCenter(marker);
|
const center = locatorMarkerCenter(marker);
|
||||||
if (center) {
|
if (center) {
|
||||||
setSelectedLocatorMarker(marker);
|
setSelectedLocatorMarker(marker);
|
||||||
setMapRadioPathTo(center.lat, center.lon, "locator-radio-path");
|
const lEntry = locatorEntryForMarker(marker);
|
||||||
|
const lColor = lEntry ? locatorStyleForEntry(lEntry, locatorEntryCount(lEntry)).color : locatorFilterColor(marker.__trxType);
|
||||||
|
setMapRadioPathTo(center.lat, center.lon, lColor, "locator-radio-path");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -5061,7 +5078,9 @@ window.navigateToMapLocator = function(grid, preferredType = null) {
|
|||||||
if (center) {
|
if (center) {
|
||||||
const targetZoom = Math.max(aprsMap.getZoom() || 0, 7);
|
const targetZoom = Math.max(aprsMap.getZoom() || 0, 7);
|
||||||
aprsMap.setView([center.lat, center.lon], targetZoom);
|
aprsMap.setView([center.lat, center.lon], targetZoom);
|
||||||
setMapRadioPathTo(center.lat, center.lon, "locator-radio-path");
|
const fEntry = locatorEntryForMarker(marker);
|
||||||
|
const fColor = fEntry ? locatorStyleForEntry(fEntry, locatorEntryCount(fEntry)).color : locatorFilterColor(marker?.__trxType);
|
||||||
|
setMapRadioPathTo(center.lat, center.lon, fColor, "locator-radio-path");
|
||||||
}
|
}
|
||||||
setSelectedLocatorMarker(marker);
|
setSelectedLocatorMarker(marker);
|
||||||
if (typeof marker.openPopup === "function") marker.openPopup();
|
if (typeof marker.openPopup === "function") marker.openPopup();
|
||||||
|
|||||||
@@ -1816,13 +1816,11 @@ body.map-fake-fullscreen-active {
|
|||||||
color: var(--text);
|
color: var(--text);
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
.aprs-radio-path { stroke: var(--accent-green) !important; stroke-opacity: 0.8 !important; stroke-dasharray: 10 5 !important; animation: aprs-radio-path-flow 0.7s linear infinite; }
|
.aprs-radio-path { stroke-dasharray: 10 5 !important; animation: aprs-radio-path-flow 0.7s linear infinite; }
|
||||||
.locator-radio-path { stroke: var(--accent-green) !important; stroke-opacity: 0.9 !important; stroke-dasharray: 12 6 !important; animation: aprs-radio-path-flow 0.7s linear infinite; }
|
.locator-radio-path { stroke-dasharray: 12 6 !important; animation: aprs-radio-path-flow 0.7s linear infinite; }
|
||||||
.decode-contact-path {
|
.decode-contact-path {
|
||||||
stroke: color-mix(in srgb, var(--accent-green) 72%, var(--accent-yellow)) !important;
|
|
||||||
stroke-opacity: 0.78 !important;
|
|
||||||
stroke-dasharray: 9 6 !important;
|
stroke-dasharray: 9 6 !important;
|
||||||
filter: drop-shadow(0 0 3px color-mix(in srgb, var(--accent-green) 34%, transparent));
|
filter: drop-shadow(0 0 3px color-mix(in srgb, currentColor 34%, transparent));
|
||||||
animation: aprs-radio-path-flow 0.85s linear infinite;
|
animation: aprs-radio-path-flow 0.85s linear infinite;
|
||||||
}
|
}
|
||||||
.decode-contact-distance-label {
|
.decode-contact-distance-label {
|
||||||
|
|||||||
Reference in New Issue
Block a user