export const BeaconMap = { mounted() { const lat = parseFloat(this.el.dataset.lat) const lon = parseFloat(this.el.dataset.lon) const label = this.el.dataset.label || "" const onTheAir = this.el.dataset.onTheAir === "true" const cells = JSON.parse(this.el.dataset.cells || "[]") const step = parseFloat(this.el.dataset.gridStep || "0.125") const map = L.map(this.el, { zoomControl: true, attributionControl: false, scrollWheelZoom: false }).setView([lat, lon], 9) L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { maxZoom: 19 }).addTo(map) // Draw each HRRR grid cell as a filled rectangle colored by its received // signal tier. Use a single layerGroup so zoom/pan stays fast. const cellLayer = L.layerGroup().addTo(map) const half = step / 2.0 const allBounds = [] for (const c of cells) { const sw = [c.lat - half, c.lon - half] const ne = [c.lat + half, c.lon + half] const rect = L.rectangle([sw, ne], { color: c.color, weight: 0, fillColor: c.color, fillOpacity: 0.55, interactive: true }) rect.bindTooltip( `${c.label}
${c.rx_dbm} dBm
${c.distance_km} km ยท score ${c.score}`, {sticky: true} ) rect.addTo(cellLayer) allBounds.push(sw, ne) } // Beacon marker on top. const markerColor = onTheAir ? "#16a34a" : "#94a3b8" const markerFill = onTheAir ? "#22c55e" : "#cbd5e1" L.circleMarker([lat, lon], { radius: 7, color: markerColor, fillColor: markerFill, fillOpacity: 1.0, weight: 2 }).addTo(map).bindTooltip(label, { permanent: true, direction: "top", offset: [0, -10] }) // Fit to the rendered cells (initial view already set above), then zoom // in two steps so the beacon's immediate surroundings are visible. if (allBounds.length > 0) { map.fitBounds(L.latLngBounds(allBounds), {padding: [20, 20]}) map.setZoom(map.getZoom() + 2) } setTimeout(() => map.invalidateSize(), 50) } }