From 4e4c1337c98803254eb80a02a07a1d30719dc1e4 Mon Sep 17 00:00:00 2001 From: Zefire85 Date: Mon, 25 Nov 2024 00:46:11 +0100 Subject: [PATCH] Distance measurer toggle button and fix copy coordinates bug (#4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix copy coordinates triggering popup marker twice due to inability to remove map interaction listener. This caused incompatibility with distance measurer and could have other unwanted effects. Co-authored-by: Antti Ellilä --- copy-coordinates/BlueMapCopyCoordinates.js | 20 ++- distance-measurer/BlueMapDistanceMeasurer.js | 137 ++++++++++++++----- 2 files changed, 113 insertions(+), 44 deletions(-) diff --git a/copy-coordinates/BlueMapCopyCoordinates.js b/copy-coordinates/BlueMapCopyCoordinates.js index ef53eee..7067b36 100644 --- a/copy-coordinates/BlueMapCopyCoordinates.js +++ b/copy-coordinates/BlueMapCopyCoordinates.js @@ -38,11 +38,7 @@ window.copyText = function (data) { document.body.removeChild(temp); }; -const originalOnMapInteraction = window.bluemap.popupMarker.onMapInteraction; -window.bluemap.events.removeEventListener("bluemapMapInteraction", originalOnMapInteraction); - -window.bluemap.popupMarker.onMapInteraction = function(evt) { - originalOnMapInteraction.call(this, evt); +hijack(bluemap.popupMarker, "open", (original) => function() { poiCounter++; const key = `${poiLabel}-${poiCounter}`; const data = { @@ -67,6 +63,16 @@ window.bluemap.popupMarker.onMapInteraction = function(evt) { copyButtonDiv.appendChild(button); this.element.appendChild(copyButtonDiv); -}.bind(window.bluemap.popupMarker); -window.bluemap.events.addEventListener("bluemapMapInteraction", window.bluemap.popupMarker.onMapInteraction); + return original.call(this); +}.bind(bluemap.popupMarker)); + +/** + * Hijack a function with custom behavior + * @param {object} object Context object containing the function + * @param {string} funcName Name of the function to hijack + * @param {(original: function) => function} override Override function that wraps the original + */ +function hijack(object, funcName, override) { + object[funcName] = override(object[funcName]); +} diff --git a/distance-measurer/BlueMapDistanceMeasurer.js b/distance-measurer/BlueMapDistanceMeasurer.js index 6c05753..e9279bc 100644 --- a/distance-measurer/BlueMapDistanceMeasurer.js +++ b/distance-measurer/BlueMapDistanceMeasurer.js @@ -1,50 +1,113 @@ +// Toggle button +const rulerSvg = ``; +const toggleBtnControl = document.createElement("div"); +toggleBtnControl.className = "svg-button distance-toggle"; +toggleBtnControl.innerHTML = rulerSvg; +const toggleBtnZoom = toggleBtnControl.cloneNode(true); +const spacer = document.createElement("div"); +spacer.className = "space thin-hide"; +const cb = document.querySelector(".control-bar"); +const cbReference = [...cb.children].find((el) => el.className === "space thin-hide greedy"); +cbReference.parentNode.insertBefore(spacer, cbReference); +cbReference.parentNode.insertBefore(toggleBtnControl, cbReference); +const zb = document.querySelector("#zoom-buttons"); +zb.insertBefore(toggleBtnZoom, zb.children[0]); +const styles = document.createElement("style"); +styles.innerHTML = /* css */ ` + #zoom-buttons > .distance-toggle { + display: none; + margin-bottom: 0.5em; + } + .control-bar > .distance-toggle { + display: block; + } + @media (max-width: 575.98px) { + #zoom-buttons > .distance-toggle { + display: block; + } + .control-bar > .distance-toggle { + display: none; + } + } +`; +document.body.appendChild(styles); + +// State +let isDistanceLineVisible = false; const positions = []; + +// Distance line marker const distanceLineMarker = new BlueMap.LineMarker("distanceLineMarker"); distanceLineMarker.line.depthTest = false; distanceLineMarker.line.linewidth = 2; distanceLineMarker.data.listed = false; +distanceLineMarker.visible = isDistanceLineVisible; bluemap.popupMarkerSet.add(distanceLineMarker); -hijack(bluemap.popupMarker, 'open', function (original) { - return function () { - const pos = bluemap.popupMarker.position; - positions.push([pos.x, pos.y, pos.z]); - - if (positions.length === 2) { - const prevPos = positions[0]; - const newPos = positions[1]; - const distance = Math.sqrt(Math.pow(prevPos[0] - newPos[0], 2) + Math.pow(prevPos[1] - newPos[1], 2) + Math.pow(prevPos[2] - newPos[2], 2)); - console.log("Distance between " + prevPos + " and " + newPos + " is " + distance); - distanceLineMarker.data.label = "Distance: " + distance.toFixed(2) + " blocks"; - - const avgX = (prevPos[0] + newPos[0]) / 2; - const avgY = (prevPos[1] + newPos[1]) / 2; - const avgZ = (prevPos[2] + newPos[2]) / 2; - distanceLineMarker.position = {x: avgX, y: avgY, z: avgZ}; - - const points = [ - prevPos[0] - avgX + 0.5, prevPos[1] - avgY + 1, prevPos[2] - avgZ + 0.5, - newPos[0] - avgX + 0.5, newPos[1] - avgY + 1, newPos[2] - avgZ + 0.5 - ]; - distanceLineMarker.setLine(points); - - //remove the first element - positions.shift(); - } - original.call(this); - }; +// Toggle +function toggleDistanceLine() { + isDistanceLineVisible = !isDistanceLineVisible; + distanceLineMarker.visible = isDistanceLineVisible; + if (isDistanceLineVisible) { + toggleBtnControl.classList.add("active"); + toggleBtnZoom.classList.add("active"); + } else { + toggleBtnControl.classList.remove("active"); + toggleBtnZoom.classList.remove("active"); + } +} +toggleBtnControl.addEventListener("click", toggleDistanceLine); +toggleBtnZoom.addEventListener("click", toggleDistanceLine); + +// Hijack the 'open' method of popupMarker to track positions +hijack(bluemap.popupMarker, "open", (original) => function () { + const pos = bluemap.popupMarker.position; + positions.push([pos.x, pos.y, pos.z]); + + // Ensure we have two distinct positions before measuring + if (positions.length === 2) { + const prevPos = positions[0]; + const newPos = positions[1]; + + // Calculate the Euclidean distance between the two points + const distance = Math.sqrt( + Math.pow(prevPos[0] - newPos[0], 2) + + Math.pow(prevPos[1] - newPos[1], 2) + + Math.pow(prevPos[2] - newPos[2], 2) + ); + console.log("Distance between " + prevPos + " and " + newPos + " is " + distance); + distanceLineMarker.data.label = "Distance: " + distance.toFixed(2) + " blocks"; + + // Calculate the average position for marker placement + const avgX = (prevPos[0] + newPos[0]) / 2; + const avgY = (prevPos[1] + newPos[1]) / 2; + const avgZ = (prevPos[2] + newPos[2]) / 2; + distanceLineMarker.position = { x: avgX, y: avgY, z: avgZ }; + + // Set the line points relative to the average position + const points = [ + prevPos[0] - avgX + 0.5, + prevPos[1] - avgY + 1, + prevPos[2] - avgZ + 0.5, + newPos[0] - avgX + 0.5, + newPos[1] - avgY + 1, + newPos[2] - avgZ + 0.5, + ]; + distanceLineMarker.setLine(points); + + // Remove the first position to prepare for the next measurement + positions.shift(); + } + + original.call(this); // Call the original 'open' function of popupMarker }); /** - * Hijack a function with custom behaviour - * from https://gist.github.com/joshwnj/625349/ - * @param {object} Context object - * @param {string} Name of the context object's function - * @param {function} Override function - * @return {function} Original function + * Hijack a function with custom behavior + * @param {object} object Context object containing the function + * @param {string} funcName Name of the function to hijack + * @param {(original: function) => function} override Override function that wraps the original */ function hijack(object, funcName, override) { - var original = object[funcName]; - object[funcName] = override(original); - return original; + object[funcName] = override(object[funcName]); }