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
+90
-3
@@ -70,6 +70,11 @@ const lmeState = {
|
||||
compassVisible: false,
|
||||
compassMode: "fixed",
|
||||
compassHeading: 0,
|
||||
compassDisplayRotation: 0,
|
||||
compassTargetRotation: 0,
|
||||
compassHeadingInitialized: false,
|
||||
compassAnimationFrame: null,
|
||||
compassAnimationTime: 0,
|
||||
compassPosition: null,
|
||||
compassDragCleanup: null,
|
||||
compassResizeHandler: null,
|
||||
@@ -87,6 +92,7 @@ const lmeState = {
|
||||
managerHighlightedParentRecords: null,
|
||||
managerHoveredParentKey: null,
|
||||
managerHoveredParentRecords: null,
|
||||
managerDirectHighlightStyles: new Map(),
|
||||
managerOutsideSelectionBound: false,
|
||||
managerHiddenObjects: new Map(),
|
||||
managerHiddenObjectIds: new Set(),
|
||||
@@ -496,6 +502,7 @@ function createCompassLayer() {
|
||||
updateCompassDisplay();
|
||||
},
|
||||
onRemove(map) {
|
||||
stopCompassAnimation();
|
||||
lmeState.compassDragCleanup?.();
|
||||
lmeState.compassDragCleanup = null;
|
||||
if (lmeState.compassResizeHandler) {
|
||||
@@ -623,6 +630,7 @@ function setCompassOptions(visible, mode = "fixed") {
|
||||
lmeState.compassLayer.addTo(lmeState.map);
|
||||
}
|
||||
} else {
|
||||
stopCompassAnimation();
|
||||
lmeState.managerHiddenCategories.add("compass");
|
||||
if (lmeState.map.hasLayer(lmeState.compassLayer)) {
|
||||
lmeState.map.removeLayer(lmeState.compassLayer);
|
||||
@@ -641,19 +649,67 @@ function setCompassOptions(visible, mode = "fixed") {
|
||||
function setCompassHeading(heading) {
|
||||
const parsed = Number(heading);
|
||||
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") {
|
||||
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();
|
||||
}
|
||||
|
||||
function stopCompassAnimation() {
|
||||
if (lmeState.compassAnimationFrame !== null) {
|
||||
cancelAnimationFrame(lmeState.compassAnimationFrame);
|
||||
lmeState.compassAnimationFrame = null;
|
||||
}
|
||||
lmeState.compassAnimationTime = 0;
|
||||
}
|
||||
|
||||
function updateCompassDisplay() {
|
||||
const element = lmeState.compassElement;
|
||||
if (!element) return;
|
||||
const rotation = -lmeState.compassHeading;
|
||||
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"
|
||||
? `Bussola: mappa con nord fisso, orientamento ${Math.round(lmeState.compassHeading)} gradi`
|
||||
: `Bussola: nord, orientamento ${Math.round(lmeState.compassHeading)} gradi`);
|
||||
@@ -4085,7 +4141,9 @@ function renderSelectedManagerHighlight() {
|
||||
}
|
||||
|
||||
function renderManagerHighlight(records) {
|
||||
restoreDirectManagerHighlights();
|
||||
lmeState.managerHighlight?.clearLayers();
|
||||
records.forEach(record => applyDirectManagerHighlight(record.layer));
|
||||
const features = records.flatMap(record => {
|
||||
const geojson = record.layer?.toGeoJSON?.();
|
||||
if (!geojson) {
|
||||
@@ -4112,7 +4170,36 @@ function renderManagerHighlight(records) {
|
||||
}).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() {
|
||||
restoreDirectManagerHighlights();
|
||||
lmeState.managerHighlight?.clearLayers();
|
||||
lmeState.managerHighlightedObjectId = null;
|
||||
lmeState.managerHighlightedCategoryKey = null;
|
||||
|
||||
Reference in new issue
Block a user