From 4ada5761e69093405fe85a0801006b83340df02a Mon Sep 17 00:00:00 2001 From: franmagn Date: Wed, 5 Nov 2025 14:21:06 +0100 Subject: [PATCH] feat(#47): visualize name labels OR value labels, or hide both now it is not possible to see both name labels and value labels of the measurements, and it's possible to switch between these visualization thanks to two new buttons. There is also the possibility to hide both with a third button, all in the same section of the sidebar --- src/MeasurementControl/measurementsPanel.js | 99 ++++++++++++++++++++- 1 file changed, 97 insertions(+), 2 deletions(-) diff --git a/src/MeasurementControl/measurementsPanel.js b/src/MeasurementControl/measurementsPanel.js index bc47e2f..aef16fd 100644 --- a/src/MeasurementControl/measurementsPanel.js +++ b/src/MeasurementControl/measurementsPanel.js @@ -70,6 +70,8 @@ export function initMeasurementsPanel(viewer) { const renderArea = document.getElementById('potree_render_area') let overlay = null const overlayMap = new Map() // uuid -> label element + // set default display mode of the label buttons + let measurementDisplayMode = 'VALUES' if (renderArea) { overlay = document.createElement('div') overlay.id = 'measurement_label_overlay' @@ -204,6 +206,10 @@ export function initMeasurementsPanel(viewer) { overlayMap.set(measurement.uuid, lbl) } lbl.textContent = labelText || '' + try { + // only show overlay name labels when in NAMES mode + lbl.style.display = measurementDisplayMode === 'NAMES' ? '' : 'none' + } catch (e) {} return lbl } @@ -226,7 +232,8 @@ export function initMeasurementsPanel(viewer) { if (!pos || !pos.visible) { el.style.display = 'none' } else { - el.style.display = '' + // Only show overlay name labels when NAMES mode is active + el.style.display = measurementDisplayMode === 'NAMES' ? '' : 'none' el.style.left = Math.round(pos.x) + 'px' el.style.top = Math.round(pos.y) + 'px' } @@ -272,7 +279,9 @@ export function initMeasurementsPanel(viewer) { const originalPropertiesPanel = document.querySelector( '#scene_object_properties' ) - // This section is for moving the "scene" object to the meaasurements tab, only if the measurements section is selected, so that all other folders (like camera) stays where it should be + // This section is for moving the "scene" object to the meaasurements tab, + // only if the measurements section is selected, so that all other folders + // (like camera) stays where it should be let placeholder = null let originalParent = null function ensurePlaceholder() { @@ -1219,6 +1228,32 @@ export function initMeasurementsPanel(viewer) { if (toolsHost) { const measOptions = document.getElementById('measurement_options_show') if (measOptions) { + // Replace the built two-option control with a three-option label handling + try { + const hasValues = + !!measOptions.querySelector('#measurement_options_show_values') || + !!measOptions.querySelector('option[value="VALUES"]') + if (!hasValues) { + measOptions.innerHTML = `\n + \n + \n + \n + ` + } + + if ( + window && + window.jQuery && + typeof $(measOptions).selectgroup === 'function' + ) { + try { + $(measOptions).selectgroup({ title: 'Show/Hide labels' }) + // trigger the VALUES option so UI appears selected and handlers run + const $val = $(measOptions).find('input[value="VALUES"]') + if ($val.length) $val.trigger('click') + } catch (e) {} + } + } catch (e) {} const measLi = measOptions.closest('li') || measOptions if (measLi && !measLi.classList.contains('measurement-options-block')) { measLi.classList.add('measurement-options-block') @@ -1238,6 +1273,66 @@ export function initMeasurementsPanel(viewer) { if (measLi && measLi.parentElement !== toolsHost) { toolsHost.appendChild(measLi) } + // Force initial VALUES mode here + try { + if (window && window.jQuery) { + $(document).trigger('measurement_display_mode', ['VALUES']) + } + // also set Potree measuring tool state directly if present + if (viewer && viewer.measuringTool) { + try { + viewer.measuringTool.showLabels = true // show numeric/value labels + } catch (e) {} + } + } catch (e) {} + } + } + + // Listen for measurement display mode events (VALUES / NAMES / HIDE) + // and toggle the overlay name labels we create in this panel. + try { + const applyDisplayMode = (mode) => { + // remember the chosen mode so new overlays follow it + measurementDisplayMode = mode || measurementDisplayMode + if (!overlay || !overlayMap) return + for (const el of overlayMap.values()) { + if (!el) continue + if (measurementDisplayMode === 'NAMES') { + // show name overlays + el.style.display = '' + } else { + // hide name overlays in both VALUES and HIDE modes + el.style.display = 'none' + } + } + // Also ensure the measuringTool's numeric/value labels follow the mode. + try { + if (viewer && viewer.measuringTool) { + // show numeric/value labels only in VALUES mode + viewer.measuringTool.showLabels = measurementDisplayMode === 'VALUES' + } + } catch (e) {} + } + + // If jQuery triggers the custom event from potree toolbar, handle it + if (window && window.jQuery) { + $(document).on('measurement_display_mode', (e, mode) => { + applyDisplayMode(mode) + }) + } + + // Also attach a direct listener to input clicks inside the control in case + // the selectgroup implementation creates native inputs. + const measEl = document.getElementById('measurement_options_show') + if (measEl) { + measEl.addEventListener('click', (ev) => { + const input = + ev.target && ev.target.closest && ev.target.closest('input') + const value = input ? input.value : null + if (value) applyDisplayMode(value) + }) } + } catch (e) { + // non-fatal if event hooks cannot be installed } }