Add 6-char subsquare grid overlay and fix map edge rendering
- Show subsquares (5' x 2.5') at zoom >= 11 with lighter styling - Pad map bounds by 10% so edge tiles always have score data - Re-send bounds after 500ms to catch late container layout changes
This commit is contained in:
parent
c3becdac9f
commit
5f803e4c0d
2 changed files with 41 additions and 9 deletions
|
|
@ -73,25 +73,29 @@ function drawGridSquare(
|
||||||
c.south > bounds.getNorth() || c.north < bounds.getSouth()) return
|
c.south > bounds.getNorth() || c.north < bounds.getSouth()) return
|
||||||
|
|
||||||
const field = precision <= 2
|
const field = precision <= 2
|
||||||
|
const sub = precision >= 6
|
||||||
|
const weight = field ? 2.5 : sub ? 1 : 2
|
||||||
|
const opacity = sub ? 0.5 : 0.8
|
||||||
|
|
||||||
layerGroup.addLayer(L.rectangle(
|
layerGroup.addLayer(L.rectangle(
|
||||||
[[c.south, c.west], [c.north, c.east]],
|
[[c.south, c.west], [c.north, c.east]],
|
||||||
{ color: "#E63946", weight: field ? 2.5 : 2, opacity: 0.8, fillOpacity: 0, interactive: false }
|
{ color: "#E63946", weight, opacity, fillOpacity: 0, interactive: false }
|
||||||
))
|
))
|
||||||
|
|
||||||
const sw = map.latLngToContainerPoint([c.south, c.west])
|
const sw = map.latLngToContainerPoint([c.south, c.west])
|
||||||
const ne = map.latLngToContainerPoint([c.north, c.east])
|
const ne = map.latLngToContainerPoint([c.north, c.east])
|
||||||
const px = Math.abs(ne.x - sw.x)
|
const px = Math.abs(ne.x - sw.x)
|
||||||
const minW = field ? 30 : 40
|
const minW = sub ? 25 : field ? 30 : 40
|
||||||
if (px > minW) {
|
if (px > minW) {
|
||||||
const len = field ? 2 : 4
|
// Subsquares show just the last 2 chars (e.g. "kp"), others show full label
|
||||||
const text = grid.substring(0, len)
|
const text = sub ? grid.substring(4, 6) : grid.substring(0, field ? 2 : 4)
|
||||||
const fs = Math.max(10, Math.min(14, Math.round(px / (len * 1.2))))
|
const len = text.length
|
||||||
|
const fs = Math.max(9, Math.min(sub ? 12 : 14, Math.round(px / (len * 1.2))))
|
||||||
layerGroup.addLayer(L.marker([c.center.lat, c.center.lon], {
|
layerGroup.addLayer(L.marker([c.center.lat, c.center.lon], {
|
||||||
interactive: false,
|
interactive: false,
|
||||||
icon: L.divIcon({
|
icon: L.divIcon({
|
||||||
className: "grid-label",
|
className: "grid-label",
|
||||||
html: `<div style="font-size:${fs}px;font-weight:bold;color:#fff;background:rgba(0,0,0,0.5);padding:1px 4px;border-radius:3px;white-space:nowrap;width:fit-content;">${text}</div>`,
|
html: `<div style="font-size:${fs}px;font-weight:${sub ? "normal" : "bold"};color:#fff;background:rgba(0,0,0,${sub ? "0.35" : "0.5"});padding:1px 4px;border-radius:3px;white-space:nowrap;width:fit-content;">${text}</div>`,
|
||||||
iconSize: [Math.round(len * fs * 0.8), Math.round(fs * 1.5)],
|
iconSize: [Math.round(len * fs * 0.8), Math.round(fs * 1.5)],
|
||||||
iconAnchor: [Math.round(len * fs * 0.4), Math.round(fs * 0.75)]
|
iconAnchor: [Math.round(len * fs * 0.4), Math.round(fs * 0.75)]
|
||||||
})
|
})
|
||||||
|
|
@ -105,6 +109,7 @@ export function updateGridOverlay(map: L.Map, gridLayer: L.LayerGroup): void {
|
||||||
const bounds = map.getBounds()
|
const bounds = map.getBounds()
|
||||||
const zoom = map.getZoom()
|
const zoom = map.getZoom()
|
||||||
const showSquares = zoom >= 7
|
const showSquares = zoom >= 7
|
||||||
|
const showSubsquares = zoom >= 11
|
||||||
|
|
||||||
const south = Math.max(bounds.getSouth(), -90)
|
const south = Math.max(bounds.getSouth(), -90)
|
||||||
const north = Math.min(bounds.getNorth(), 90)
|
const north = Math.min(bounds.getNorth(), 90)
|
||||||
|
|
@ -133,8 +138,32 @@ export function updateGridOverlay(map: L.Map, gridLayer: L.LayerGroup): void {
|
||||||
for (let lon = wE; lon < eE; lon += 2) {
|
for (let lon = wE; lon < eE; lon += 2) {
|
||||||
for (let lat = sE; lat < nE; lat += 1) {
|
for (let lat = sE; lat < nE; lat += 1) {
|
||||||
const nLon = ((lon % 360) + 540) % 360 - 180
|
const nLon = ((lon % 360) + 540) % 360 - 180
|
||||||
const g = new GridSquare(lat + 0.5, nLon + 1).encode(4)
|
|
||||||
drawGridSquare(g.substring(0, 4), 4, bounds, gridLayer, drawn, map)
|
if (showSubsquares) {
|
||||||
|
// Draw the 4-char square boundary first
|
||||||
|
const sq = new GridSquare(lat + 0.5, nLon + 1).encode(4)
|
||||||
|
drawGridSquare(sq.substring(0, 4), 4, bounds, gridLayer, drawn, map)
|
||||||
|
|
||||||
|
// Then draw 6-char subsquares (24 x 24 = 576 per square, 5' x 2.5')
|
||||||
|
const subW = 5 / 60
|
||||||
|
const subH = 2.5 / 60
|
||||||
|
const startI = Math.max(0, Math.floor((bounds.getWest() - lon) / subW))
|
||||||
|
const endI = Math.min(24, Math.ceil((bounds.getEast() - lon) / subW))
|
||||||
|
const startJ = Math.max(0, Math.floor((bounds.getSouth() - lat) / subH))
|
||||||
|
const endJ = Math.min(24, Math.ceil((bounds.getNorth() - lat) / subH))
|
||||||
|
|
||||||
|
for (let i = startI; i < endI; i++) {
|
||||||
|
for (let j = startJ; j < endJ; j++) {
|
||||||
|
const cLon = nLon + i * subW + subW / 2
|
||||||
|
const cLat = lat + j * subH + subH / 2
|
||||||
|
const sub = new GridSquare(cLat, cLon).encode(6)
|
||||||
|
drawGridSquare(sub, 6, bounds, gridLayer, drawn, map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const g = new GridSquare(lat + 0.5, nLon + 1).encode(4)
|
||||||
|
drawGridSquare(g.substring(0, 4), 4, bounds, gridLayer, drawn, map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -852,6 +852,8 @@ export const PropagationMap: Record<string, unknown> & {
|
||||||
this.el.addEventListener("show-loading", () => topbar.show(300))
|
this.el.addEventListener("show-loading", () => topbar.show(300))
|
||||||
|
|
||||||
requestAnimationFrame(() => this.sendBounds())
|
requestAnimationFrame(() => this.sendBounds())
|
||||||
|
// Re-check bounds after layout settles (sidebar, fonts, etc.)
|
||||||
|
setTimeout(() => { this.map.invalidateSize(); this.sendBounds() }, 500)
|
||||||
this.map.on("moveend", () => {
|
this.map.on("moveend", () => {
|
||||||
this.sendBounds()
|
this.sendBounds()
|
||||||
if (this.gridVisible) {
|
if (this.gridVisible) {
|
||||||
|
|
@ -1124,7 +1126,8 @@ export const PropagationMap: Record<string, unknown> & {
|
||||||
|
|
||||||
sendBounds(this: PropagationMapHook) {
|
sendBounds(this: PropagationMapHook) {
|
||||||
topbar.show()
|
topbar.show()
|
||||||
const b = this.map.getBounds()
|
// Pad bounds by ~0.5° so Leaflet edge tiles always have data to render
|
||||||
|
const b = this.map.getBounds().pad(0.1)
|
||||||
this.pushEvent("map_bounds", {
|
this.pushEvent("map_bounds", {
|
||||||
south: b.getSouth(),
|
south: b.getSouth(),
|
||||||
north: b.getNorth(),
|
north: b.getNorth(),
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue