Smooth compass and strengthen map selection
This commit is contained in:
1 parent
8a8fc1dfe4
commit
a0e24fc925
5 files changed
+96
-10
No files matched your search
@@ -102,7 +102,7 @@
|
|||||||
],
|
],
|
||||||
"tools" =>
|
"tools" =>
|
||||||
[
|
[
|
||||||
"Tabella oggetti: apre una vista ordinata di particelle, file importati e disegni. Usa i flag per selezionare piu righe, il lucchetto per proteggerle e la matita per modificare i metadati.",
|
"Tabella oggetti: apre una vista ordinata di particelle, file importati e disegni. Usa i flag per selezionare piu righe, evidenziate sulla mappa con contorno magenta e riempimento ciano; il lucchetto le protegge e la matita modifica i metadati.",
|
||||||
"Colonna Note: il pulsante Note e sempre attivo e apre tutte le note dell'oggetto. La consultazione resta disponibile anche senza Pro; aggiunta, modifica ed eliminazione richiedono abbonamento o licenza manuale.",
|
"Colonna Note: il pulsante Note e sempre attivo e apre tutte le note dell'oggetto. La consultazione resta disponibile anche senza Pro; aggiunta, modifica ed eliminazione richiedono abbonamento o licenza manuale.",
|
||||||
"Copia metadati: nella maschera Metadati oggetto scegli Copia da e l'oggetto sorgente. Attiva Importa anche i valori per copiare nomi e contenuti; disattivalo per creare soltanto gli stessi campi, lasciandoli vuoti o mantenendo i valori gia presenti.",
|
"Copia metadati: nella maschera Metadati oggetto scegli Copia da e l'oggetto sorgente. Attiva Importa anche i valori per copiare nomi e contenuti; disattivalo per creare soltanto gli stessi campi, lasciandoli vuoti o mantenendo i valori gia presenti.",
|
||||||
"Coordinate WGS84 e UTM: scegli un punto sulla mappa per leggere latitudine e longitudine oppure le coordinate metriche UTM, utili per rilievi e confronti tecnici.",
|
"Coordinate WGS84 e UTM: scegli un punto sulla mappa per leggere latitudine e longitudine oppure le coordinate metriche UTM, utili per rilievi e confronti tecnici.",
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
"settings" =>
|
"settings" =>
|
||||||
[
|
[
|
||||||
"Mappa e sfondo: scegli la cartografia di base e regola Trasparenza catasto per leggere meglio confini e immagini sottostanti. Esempio: riducila quando le linee coprono dettagli del terreno.",
|
"Mappa e sfondo: scegli la cartografia di base e regola Trasparenza catasto per leggere meglio confini e immagini sottostanti. Esempio: riducila quando le linee coprono dettagli del terreno.",
|
||||||
"Bussola: attiva Mostra bussola per visualizzare N, NE, E, SE, S, SW, W e NW. Puoi trascinarla nella posizione preferita. Con nord fisso la mappa non ruota e la lancetta indica il nord; in modalita Navigatore la mappa segue l'orientamento del dispositivo.",
|
"Bussola: attiva Mostra bussola per visualizzare N, NE, E, SE, S, SW, W e NW. Puoi trascinarla nella posizione preferita. La modalita predefinita mantiene il nord della mappa fisso in alto e la lancetta indica il nord con movimento continuo; in modalita Navigatore la mappa segue l'orientamento del dispositivo.",
|
||||||
"Messaggi mappa: scegli dopo quanti secondi devono chiudersi automaticamente; imposta 0 per mantenerli finche non premi la X.",
|
"Messaggi mappa: scegli dopo quanti secondi devono chiudersi automaticamente; imposta 0 per mantenerli finche non premi la X.",
|
||||||
"Autosalvataggio locale dopo ogni modifica: se attivo, ogni disegno, modifica, rinomina o eliminazione aggiorna immediatamente una copia di recupero nel dispositivo. Per usarla apri Dati e disegni e premi Recupera ultimo autosalvataggio.",
|
"Autosalvataggio locale dopo ogni modifica: se attivo, ogni disegno, modifica, rinomina o eliminazione aggiorna immediatamente una copia di recupero nel dispositivo. Per usarla apri Dati e disegni e premi Recupera ultimo autosalvataggio.",
|
||||||
"Aggiorna automaticamente il progetto aperto: funziona solo dopo aver aperto o salvato un progetto modificabile. Dopo una modifica attende 3 secondi senza altre operazioni e aggiorna quel progetto; un progetto in sola lettura non viene mai sovrascritto.",
|
"Aggiorna automaticamente il progetto aperto: funziona solo dopo aver aperto o salvato un progetto modificabile. Dopo una modifica attende 3 secondi senza altre operazioni e aggiorna quel progetto; un progetto in sola lettura non viene mai sovrascritto.",
|
||||||
|
|||||||
@@ -681,7 +681,7 @@
|
|||||||
<label>
|
<label>
|
||||||
Orientamento bussola
|
Orientamento bussola
|
||||||
<select @bind="CompassMode" @bind:after="ApplyCompassOptions" disabled="@(!ShowCompass)">
|
<select @bind="CompassMode" @bind:after="ApplyCompassOptions" disabled="@(!ShowCompass)">
|
||||||
<option value="fixed">Mappa: nord fisso in alto</option>
|
<option value="fixed">Mappa: nord fisso in alto (predefinito)</option>
|
||||||
<option value="heading">Navigatore: direzione del dispositivo in alto</option>
|
<option value="heading">Navigatore: direzione del dispositivo in alto</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
@@ -2871,7 +2871,7 @@
|
|||||||
{
|
{
|
||||||
compass.ReadingChanged += OnCompassReadingChanged;
|
compass.ReadingChanged += OnCompassReadingChanged;
|
||||||
CompassSensorSubscribed = true;
|
CompassSensorSubscribed = true;
|
||||||
compass.Start(Microsoft.Maui.Devices.Sensors.SensorSpeed.UI);
|
compass.Start(Microsoft.Maui.Devices.Sensors.SensorSpeed.Game, applyLowPassFilter: true);
|
||||||
}
|
}
|
||||||
else if (!shouldMonitor && CompassSensorSubscribed)
|
else if (!shouldMonitor && CompassSensorSubscribed)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,8 +29,8 @@
|
|||||||
<ApplicationId>it.liviomerola.lmemappecatastali.pro</ApplicationId>
|
<ApplicationId>it.liviomerola.lmemappecatastali.pro</ApplicationId>
|
||||||
|
|
||||||
<!-- Versions -->
|
<!-- Versions -->
|
||||||
<ApplicationDisplayVersion>1.0.22</ApplicationDisplayVersion>
|
<ApplicationDisplayVersion>1.0.23</ApplicationDisplayVersion>
|
||||||
<ApplicationVersion>122</ApplicationVersion>
|
<ApplicationVersion>123</ApplicationVersion>
|
||||||
<Version>$(ApplicationDisplayVersion)</Version>
|
<Version>$(ApplicationDisplayVersion)</Version>
|
||||||
|
|
||||||
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
|
<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
|
||||||
|
|||||||
@@ -1868,7 +1868,6 @@ label {
|
|||||||
transform-origin: 50% 100%;
|
transform-origin: 50% 100%;
|
||||||
border-radius: 4px 4px 1px 1px;
|
border-radius: 4px 4px 1px 1px;
|
||||||
background: #ef4444;
|
background: #ef4444;
|
||||||
transition: transform 120ms linear;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.map-compass-needle::after {
|
.map-compass-needle::after {
|
||||||
|
|||||||
+90
-3
@@ -70,6 +70,11 @@ const lmeState = {
|
|||||||
compassVisible: false,
|
compassVisible: false,
|
||||||
compassMode: "fixed",
|
compassMode: "fixed",
|
||||||
compassHeading: 0,
|
compassHeading: 0,
|
||||||
|
compassDisplayRotation: 0,
|
||||||
|
compassTargetRotation: 0,
|
||||||
|
compassHeadingInitialized: false,
|
||||||
|
compassAnimationFrame: null,
|
||||||
|
compassAnimationTime: 0,
|
||||||
compassPosition: null,
|
compassPosition: null,
|
||||||
compassDragCleanup: null,
|
compassDragCleanup: null,
|
||||||
compassResizeHandler: null,
|
compassResizeHandler: null,
|
||||||
@@ -87,6 +92,7 @@ const lmeState = {
|
|||||||
managerHighlightedParentRecords: null,
|
managerHighlightedParentRecords: null,
|
||||||
managerHoveredParentKey: null,
|
managerHoveredParentKey: null,
|
||||||
managerHoveredParentRecords: null,
|
managerHoveredParentRecords: null,
|
||||||
|
managerDirectHighlightStyles: new Map(),
|
||||||
managerOutsideSelectionBound: false,
|
managerOutsideSelectionBound: false,
|
||||||
managerHiddenObjects: new Map(),
|
managerHiddenObjects: new Map(),
|
||||||
managerHiddenObjectIds: new Set(),
|
managerHiddenObjectIds: new Set(),
|
||||||
@@ -496,6 +502,7 @@ function createCompassLayer() {
|
|||||||
updateCompassDisplay();
|
updateCompassDisplay();
|
||||||
},
|
},
|
||||||
onRemove(map) {
|
onRemove(map) {
|
||||||
|
stopCompassAnimation();
|
||||||
lmeState.compassDragCleanup?.();
|
lmeState.compassDragCleanup?.();
|
||||||
lmeState.compassDragCleanup = null;
|
lmeState.compassDragCleanup = null;
|
||||||
if (lmeState.compassResizeHandler) {
|
if (lmeState.compassResizeHandler) {
|
||||||
@@ -623,6 +630,7 @@ function setCompassOptions(visible, mode = "fixed") {
|
|||||||
lmeState.compassLayer.addTo(lmeState.map);
|
lmeState.compassLayer.addTo(lmeState.map);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
stopCompassAnimation();
|
||||||
lmeState.managerHiddenCategories.add("compass");
|
lmeState.managerHiddenCategories.add("compass");
|
||||||
if (lmeState.map.hasLayer(lmeState.compassLayer)) {
|
if (lmeState.map.hasLayer(lmeState.compassLayer)) {
|
||||||
lmeState.map.removeLayer(lmeState.compassLayer);
|
lmeState.map.removeLayer(lmeState.compassLayer);
|
||||||
@@ -641,19 +649,67 @@ function setCompassOptions(visible, mode = "fixed") {
|
|||||||
function setCompassHeading(heading) {
|
function setCompassHeading(heading) {
|
||||||
const parsed = Number(heading);
|
const parsed = Number(heading);
|
||||||
if (!Number.isFinite(parsed)) return;
|
if (!Number.isFinite(parsed)) return;
|
||||||
lmeState.compassHeading = ((parsed % 360) + 360) % 360;
|
const normalizedHeading = ((parsed % 360) + 360) % 360;
|
||||||
|
const requestedRotation = -normalizedHeading;
|
||||||
|
lmeState.compassHeading = normalizedHeading;
|
||||||
|
if (!lmeState.compassHeadingInitialized) {
|
||||||
|
lmeState.compassHeadingInitialized = true;
|
||||||
|
lmeState.compassDisplayRotation = requestedRotation;
|
||||||
|
lmeState.compassTargetRotation = requestedRotation;
|
||||||
|
updateCompassDisplay();
|
||||||
|
} else {
|
||||||
|
const delta = shortestAngleDelta(lmeState.compassTargetRotation, requestedRotation);
|
||||||
|
if (Math.abs(delta) >= 0.15) {
|
||||||
|
lmeState.compassTargetRotation += delta;
|
||||||
|
startCompassAnimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (lmeState.compassVisible && lmeState.compassMode === "heading") {
|
if (lmeState.compassVisible && lmeState.compassMode === "heading") {
|
||||||
lmeState.map?.setHeading?.(lmeState.compassHeading, { ease: 0.2, deadzone: 1 });
|
lmeState.map?.setHeading?.(lmeState.compassHeading, { ease: 0.2, deadzone: 1 });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function shortestAngleDelta(from, to) {
|
||||||
|
return ((((to - from) + 180) % 360) + 360) % 360 - 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startCompassAnimation() {
|
||||||
|
if (lmeState.compassAnimationFrame !== null) return;
|
||||||
|
lmeState.compassAnimationTime = 0;
|
||||||
|
lmeState.compassAnimationFrame = requestAnimationFrame(animateCompass);
|
||||||
|
}
|
||||||
|
|
||||||
|
function animateCompass(timestamp) {
|
||||||
|
lmeState.compassAnimationFrame = null;
|
||||||
|
const elapsed = lmeState.compassAnimationTime
|
||||||
|
? Math.min(50, Math.max(1, timestamp - lmeState.compassAnimationTime))
|
||||||
|
: 16;
|
||||||
|
lmeState.compassAnimationTime = timestamp;
|
||||||
|
const difference = lmeState.compassTargetRotation - lmeState.compassDisplayRotation;
|
||||||
|
const smoothing = 1 - Math.exp(-elapsed / 85);
|
||||||
|
lmeState.compassDisplayRotation += difference * smoothing;
|
||||||
|
if (Math.abs(difference) < 0.05) {
|
||||||
|
lmeState.compassDisplayRotation = lmeState.compassTargetRotation;
|
||||||
|
lmeState.compassAnimationTime = 0;
|
||||||
|
} else {
|
||||||
|
lmeState.compassAnimationFrame = requestAnimationFrame(animateCompass);
|
||||||
|
}
|
||||||
updateCompassDisplay();
|
updateCompassDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stopCompassAnimation() {
|
||||||
|
if (lmeState.compassAnimationFrame !== null) {
|
||||||
|
cancelAnimationFrame(lmeState.compassAnimationFrame);
|
||||||
|
lmeState.compassAnimationFrame = null;
|
||||||
|
}
|
||||||
|
lmeState.compassAnimationTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
function updateCompassDisplay() {
|
function updateCompassDisplay() {
|
||||||
const element = lmeState.compassElement;
|
const element = lmeState.compassElement;
|
||||||
if (!element) return;
|
if (!element) return;
|
||||||
const rotation = -lmeState.compassHeading;
|
|
||||||
element.classList.toggle("is-fixed", lmeState.compassMode === "fixed");
|
element.classList.toggle("is-fixed", lmeState.compassMode === "fixed");
|
||||||
element.style.setProperty("--compass-rotation", `${rotation}deg`);
|
element.style.setProperty("--compass-rotation", `${lmeState.compassDisplayRotation}deg`);
|
||||||
element.setAttribute("aria-label", lmeState.compassMode === "fixed"
|
element.setAttribute("aria-label", lmeState.compassMode === "fixed"
|
||||||
? `Bussola: mappa con nord fisso, orientamento ${Math.round(lmeState.compassHeading)} gradi`
|
? `Bussola: mappa con nord fisso, orientamento ${Math.round(lmeState.compassHeading)} gradi`
|
||||||
: `Bussola: nord, orientamento ${Math.round(lmeState.compassHeading)} gradi`);
|
: `Bussola: nord, orientamento ${Math.round(lmeState.compassHeading)} gradi`);
|
||||||
@@ -4085,7 +4141,9 @@ function renderSelectedManagerHighlight() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderManagerHighlight(records) {
|
function renderManagerHighlight(records) {
|
||||||
|
restoreDirectManagerHighlights();
|
||||||
lmeState.managerHighlight?.clearLayers();
|
lmeState.managerHighlight?.clearLayers();
|
||||||
|
records.forEach(record => applyDirectManagerHighlight(record.layer));
|
||||||
const features = records.flatMap(record => {
|
const features = records.flatMap(record => {
|
||||||
const geojson = record.layer?.toGeoJSON?.();
|
const geojson = record.layer?.toGeoJSON?.();
|
||||||
if (!geojson) {
|
if (!geojson) {
|
||||||
@@ -4112,7 +4170,36 @@ function renderManagerHighlight(records) {
|
|||||||
}).addTo(lmeState.managerHighlight);
|
}).addTo(lmeState.managerHighlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyDirectManagerHighlight(layer) {
|
||||||
|
if (!layer || typeof layer.setStyle !== "function" || lmeState.managerDirectHighlightStyles.has(layer)) return;
|
||||||
|
const options = layer.options || {};
|
||||||
|
lmeState.managerDirectHighlightStyles.set(layer, {
|
||||||
|
color: options.color,
|
||||||
|
weight: options.weight,
|
||||||
|
opacity: options.opacity,
|
||||||
|
fillColor: options.fillColor,
|
||||||
|
fillOpacity: options.fillOpacity,
|
||||||
|
dashArray: options.dashArray ?? null
|
||||||
|
});
|
||||||
|
layer.setStyle({
|
||||||
|
color: "#ff00d4",
|
||||||
|
weight: Math.max(7, (Number(options.weight) || 2) + 4),
|
||||||
|
opacity: 1,
|
||||||
|
fillColor: "#00fff0",
|
||||||
|
fillOpacity: 0.34,
|
||||||
|
dashArray: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreDirectManagerHighlights() {
|
||||||
|
lmeState.managerDirectHighlightStyles.forEach((style, layer) => {
|
||||||
|
if (typeof layer?.setStyle === "function") layer.setStyle(style);
|
||||||
|
});
|
||||||
|
lmeState.managerDirectHighlightStyles.clear();
|
||||||
|
}
|
||||||
|
|
||||||
function clearManagerHighlight() {
|
function clearManagerHighlight() {
|
||||||
|
restoreDirectManagerHighlights();
|
||||||
lmeState.managerHighlight?.clearLayers();
|
lmeState.managerHighlight?.clearLayers();
|
||||||
lmeState.managerHighlightedObjectId = null;
|
lmeState.managerHighlightedObjectId = null;
|
||||||
lmeState.managerHighlightedCategoryKey = null;
|
lmeState.managerHighlightedCategoryKey = null;
|
||||||
|
|||||||
Reference in new issue
Block a user