// Band MHz -> color mapping const BAND_COLORS = { 1296: "#94a3b8", // slate 2304: "#a78bfa", // violet 3456: "#818cf8", // indigo 5760: "#60a5fa", // blue 10000: "#34d399", // emerald 24000: "#fbbf24", // amber 47000: "#fb923c", // orange 68000: "#f87171", // red 75000: "#e879f9", // fuchsia 122000: "#f472b6", // pink 134000: "#fb7185", // rose 241000: "#ff5555", // bright red } const BAND_LABELS = { 1296: "1296 MHz", 2304: "2304 MHz", 3456: "3456 MHz", 5760: "5760 MHz", 10000: "10 GHz", 24000: "24 GHz", 47000: "47 GHz", 68000: "68 GHz", 75000: "76 GHz", 122000: "122 GHz", 134000: "134 GHz", 241000: "241 GHz" } function bandColor(band) { return BAND_COLORS[band] || "#64748b" } export const ContactsMap = { mounted() { const contacts = JSON.parse(this.el.dataset.contacts) this.map = L.map(this.el, { center: [37.5, -96], zoom: 5, minZoom: 3, maxZoom: 14, preferCanvas: true }) L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: "© OpenStreetMap contributors", maxZoom: 19 }).addTo(this.map) // Group contacts by band for layered rendering const byBand = {} for (const c of contacts) { const band = c[4] if (!byBand[band]) byBand[band] = [] byBand[band].push(c) } // Collect all endpoint coords for endpoint density layer const endpointCounts = {} // Draw lines per band using canvas polylines const bandLayers = {} for (const [band, entries] of Object.entries(byBand)) { const color = bandColor(parseInt(band)) const lines = [] for (const c of entries) { const [lat1, lon1, lat2, lon2] = c lines.push(L.polyline([[lat1, lon1], [lat2, lon2]], { color: color, weight: 1, opacity: 0.4, interactive: false })) // Track endpoints const k1 = `${lat1.toFixed(2)},${lon1.toFixed(2)}` const k2 = `${lat2.toFixed(2)},${lon2.toFixed(2)}` endpointCounts[k1] = (endpointCounts[k1] || 0) + 1 endpointCounts[k2] = (endpointCounts[k2] || 0) + 1 } const layer = L.layerGroup(lines) bandLayers[band] = layer layer.addTo(this.map) } // Draw endpoint dots sized by density const dotLayer = L.layerGroup() for (const [key, count] of Object.entries(endpointCounts)) { const [lat, lon] = key.split(",").map(Number) const radius = Math.min(2 + Math.log2(count) * 1.5, 10) L.circleMarker([lat, lon], { radius: radius, color: "#fff", weight: 1, fillColor: "#3b82f6", fillOpacity: 0.7, interactive: false }).addTo(dotLayer) } dotLayer.addTo(this.map) // Build legend const legend = L.control({position: "bottomright"}) legend.onAdd = function() { const div = L.DomUtil.create("div") div.style.cssText = "background:rgba(30,30,40,0.9);color:#fff;padding:8px 12px;border-radius:8px;font-size:11px;line-height:1.6;" const sorted = Object.entries(byBand).sort((a, b) => parseInt(a[0]) - parseInt(b[0])) let html = "