diff --git a/README.md b/README.md index b29e8f1..769dc63 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ Supported data sources include DX Clusters, the Reverse Beacon Network (RBN), th ![Screenshot](/images/screenshot2.png) +![Screenshot](/images/screenshot3.png) + ### Accessing the public version You can access the public version's web interface at [https://spothole.app](https://spothole.app), and see [https://spothole.app/apidocs](https://spothole.app/apidocs) for the API details. diff --git a/images/screenshot3.png b/images/screenshot3.png new file mode 100644 index 0000000..22c759b Binary files /dev/null and b/images/screenshot3.png differ diff --git a/webassets/js/bands.js b/webassets/js/bands.js index dcafdd4..ecbde3a 100644 --- a/webassets/js/bands.js +++ b/webassets/js/bands.js @@ -5,6 +5,7 @@ BAND_COLUMN_CANVAS_WIDTH_EM = 4; BAND_COLUMN_FONT_SIZE = 16; BAND_COLUMN_HEIGHT_PX = BAND_COLUMN_HEIGHT_EM * BAND_COLUMN_FONT_SIZE; BAND_COLUMN_CANVAS_WIDTH_PX = BAND_COLUMN_CANVAS_WIDTH_EM * BAND_COLUMN_FONT_SIZE; +BAND_COLUMN_SPOT_DIV_HEIGHT_PX = BAND_COLUMN_FONT_SIZE * 1.6; // Load spots and populate the bands display. function loadSpots() { @@ -87,35 +88,67 @@ function updateBands() { } } - // Print the spots on the band. Each one is a div with the details, shifted down if necessary to prevent - // overlap - bandSpotsDiv = $("
"); - // Sort by frequency so we print higher frequencies later, and can bump them further down the track to prevent - // overlaps + // Prepare the spots list + var bandSpotsDiv = $("
"); + var lastSpotPxDownBand = -999; + // Sort by frequency so have a consistent order in which to plan where they will appear on the band div. spotList.sort(function(a, b) { return a.freq - b.freq; }); - var lastSpotEmDownBand = -999; - // Iterate through the spots list - spotList.forEach(s => { - // Work out how far down the div to draw it - var percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text - var emDownBand = percentDownBand * BAND_COLUMN_HEIGHT_EM; - if (emDownBand < lastSpotEmDownBand + 1.6) { - emDownBand = lastSpotEmDownBand + 1.6; // Prevent overlap - } - lastSpotEmDownBand = emDownBand; - // Calculate how many px down the band div the label appears, and store it with the spot, so we can use it - // later for drawing the lines. - var pxDownBandLabel = (emDownBand * BAND_COLUMN_FONT_SIZE) + (0.015 * BAND_COLUMN_HEIGHT_PX); - s["pxDownBandLabel"] = pxDownBandLabel; + // First calculate how we should be displaying the spots. There are three "modes" to try to place them in a + // visually appealing way: + // 1) Spaced normally, not going over the end of the band, so we populate them forwards. + // 2) Would go over the end, but the spots don't fill the band, so we populate them backwards. + // 3) Spots totally fill the band (or more), so we space them evenly starting at the top. + // In each case, we don't add anything to the DOM yet, we just calculate "pxDownBandLabel" (how far the *top* of + // the label is from the top of the div) and add that as a property to the spot for later use. + if (spotList.length >= BAND_COLUMN_HEIGHT_PX / BAND_COLUMN_SPOT_DIV_HEIGHT_PX) { + // Mode 3. + // Just lay out all spots simply, starting at 0px offset and working down with each one touching. + lastSpotPxDownBand = 0 - BAND_COLUMN_SPOT_DIV_HEIGHT_PX; + spotList.forEach(s => { + lastSpotPxDownBand = lastSpotPxDownBand + BAND_COLUMN_SPOT_DIV_HEIGHT_PX; + s["pxDownBandLabel"] = lastSpotPxDownBand; + }); + } else { + // Mode 1 or 2. Run through adding things to the list forwards as a test. + spotList.forEach(s => { + // Work out how far down the div to draw it + var percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text + var pxDownBand = percentDownBand * BAND_COLUMN_HEIGHT_PX; + if (pxDownBand < lastSpotPxDownBand + BAND_COLUMN_SPOT_DIV_HEIGHT_PX) { + pxDownBand = lastSpotPxDownBand + BAND_COLUMN_SPOT_DIV_HEIGHT_PX; // Prevent overlap + } + s["pxDownBandLabel"] = pxDownBand; + lastSpotPxDownBand = pxDownBand; + }); - // Add spot div to DOM - bandSpotsDiv.append(`
${s.dx_call}${s.dx_call} ${(s.freq/1000000).toFixed(3)} ${s.mode}
`); + // Work out if we overflowed the end. + if (lastSpotPxDownBand <= BAND_COLUMN_HEIGHT_PX) { + // Mode 1. Current positions are fine and there's nothing to do. + } else { + // Mode 2. Repeat the process but backwards, starting at the end and working upwards. + lastSpotPxDownBand = 999999; + spotList.reverse().forEach(s => { + // Work out how far down the div to draw it + var percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text + var pxDownBand = percentDownBand * BAND_COLUMN_HEIGHT_PX; + if (pxDownBand > lastSpotPxDownBand - BAND_COLUMN_SPOT_DIV_HEIGHT_PX) { + pxDownBand = lastSpotPxDownBand - BAND_COLUMN_SPOT_DIV_HEIGHT_PX; // Prevent overlap + } + s["pxDownBandLabel"] = pxDownBand; + lastSpotPxDownBand = pxDownBand; + }); + } + } + + // Now each spot is tagged with how far down the div it should go, add them to the DOM. + spotList.forEach(s => { + bandSpotsDiv.append(`
${s.dx_call}${s.dx_call} ${(s.freq/1000000).toFixed(3)} ${s.mode}
`); }); // Work out how tall the canvas should be. Normally this is matching the normal band column height, but if some // spots have gone off the end of the band markers and stretched their div, we need to resize the canvas to // match, otherwise we have nowhere to draw their connecting lines. - var canvasHeight = Math.max(BAND_COLUMN_HEIGHT_PX, (lastSpotEmDownBand+1.6) * BAND_COLUMN_FONT_SIZE); + var canvasHeight = Math.max(BAND_COLUMN_HEIGHT_PX, lastSpotPxDownBand + BAND_COLUMN_SPOT_DIV_HEIGHT_PX); maxHeightBand = Math.max(maxHeightBand, canvasHeight); // Draw horizontal or diagonal lines to join up the "real" frequency with where the spot div ended up @@ -124,7 +157,7 @@ function updateBands() { // Work out how far down the div to draw it var percentDownBand = (s.freq - band.start_freq) / (band.end_freq - band.start_freq) * 0.97; // not 100% due to fudge, the first and last dashes are not exactly at the top and bottom of the div as some space is needed for text var pxDownBandFreq = (percentDownBand + 0.015) * BAND_COLUMN_HEIGHT_PX; // same fudge but add half to put the left end of the line in the right place - var pxDownBandLabel = s["pxDownBandLabel"]; + var pxDownBandLabel = s["pxDownBandLabel"] + (BAND_COLUMN_SPOT_DIV_HEIGHT_PX / 1.75); // line should be to the vertical text-centre spot, not to the top corner // Draw the line on the canvas var ctx = bandLinesCanvas[0].getContext('2d');