feat: improve map zoom controls
This commit is contained in:
@@ -72,6 +72,7 @@ const map = new ol.Map({
|
|||||||
controls: ol.control
|
controls: ol.control
|
||||||
.defaults.defaults({ rotate: false })
|
.defaults.defaults({ rotate: false })
|
||||||
.extend([
|
.extend([
|
||||||
|
createVisibleLayersExtentControl(),
|
||||||
new ol.control.Rotate({
|
new ol.control.Rotate({
|
||||||
autoHide: true,
|
autoHide: true,
|
||||||
label: createNorthPointerIcon(),
|
label: createNorthPointerIcon(),
|
||||||
@@ -118,6 +119,21 @@ function createNorthPointerIcon() {
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createVisibleLayersExtentControl() {
|
||||||
|
const element = document.createElement("div");
|
||||||
|
element.className = "ol-visible-layers-extent ol-unselectable ol-control";
|
||||||
|
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.type = "button";
|
||||||
|
button.title = "Zoom to visible layers";
|
||||||
|
button.setAttribute("aria-label", "Zoom to visible layers");
|
||||||
|
button.textContent = "⤢";
|
||||||
|
button.addEventListener("click", () => fitToVisibleLayers());
|
||||||
|
|
||||||
|
element.append(button);
|
||||||
|
return new ol.control.Control({ element });
|
||||||
|
}
|
||||||
|
|
||||||
async function searchParcela(event) {
|
async function searchParcela(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
@@ -296,6 +312,34 @@ function fitToLayerExtent(layer) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fitToVisibleLayers() {
|
||||||
|
const visibleLayers = availableLayers.filter((layer) => selectedLayers.includes(layer.name));
|
||||||
|
const projectedExtents = visibleLayers
|
||||||
|
.filter((layer) => layer.extent && layer.extent.every(Number.isFinite))
|
||||||
|
.map((layer) => ol.proj.transformExtent(layer.extent, "EPSG:4326", "EPSG:3857"));
|
||||||
|
|
||||||
|
if (!projectedExtents.length) {
|
||||||
|
updateStatus("Select a layer with a published extent to zoom to it.", "error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const combinedExtent = projectedExtents.reduce(
|
||||||
|
(combined, extent) => [
|
||||||
|
Math.min(combined[0], extent[0]),
|
||||||
|
Math.min(combined[1], extent[1]),
|
||||||
|
Math.max(combined[2], extent[2]),
|
||||||
|
Math.max(combined[3], extent[3]),
|
||||||
|
],
|
||||||
|
[Infinity, Infinity, -Infinity, -Infinity],
|
||||||
|
);
|
||||||
|
|
||||||
|
map.getView().fit(combinedExtent, {
|
||||||
|
padding: [64, 64, 64, 64],
|
||||||
|
duration: 500,
|
||||||
|
maxZoom: 18,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function childElementsByName(node, localName) {
|
function childElementsByName(node, localName) {
|
||||||
return [...(node?.children || [])].filter((child) => child.localName === localName);
|
return [...(node?.children || [])].filter((child) => child.localName === localName);
|
||||||
}
|
}
|
||||||
|
|||||||
+53
@@ -312,6 +312,54 @@ button:disabled {
|
|||||||
top: 16px;
|
top: 16px;
|
||||||
right: 16px;
|
right: 16px;
|
||||||
left: auto;
|
left: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
background: var(--panel);
|
||||||
|
border: 1px solid var(--panel-border);
|
||||||
|
border-radius: 14px;
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-wrap .ol-zoom button,
|
||||||
|
.map-wrap .ol-visible-layers-extent button {
|
||||||
|
width: 2.0625em;
|
||||||
|
height: 2.0625em;
|
||||||
|
margin: 0;
|
||||||
|
background: linear-gradient(135deg, var(--accent) 0%, #2b9a79 100%);
|
||||||
|
color: #fffefb;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-wrap .ol-zoom button + button {
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-wrap .ol-zoom button:hover,
|
||||||
|
.map-wrap .ol-zoom button:focus,
|
||||||
|
.map-wrap .ol-visible-layers-extent button:hover,
|
||||||
|
.map-wrap .ol-visible-layers-extent button:focus {
|
||||||
|
background: linear-gradient(135deg, var(--accent-strong) 0%, var(--accent) 100%);
|
||||||
|
color: #fff;
|
||||||
|
outline: 2px solid rgba(31, 122, 98, 0.35);
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-wrap .ol-visible-layers-extent {
|
||||||
|
top: 96px;
|
||||||
|
right: 16px;
|
||||||
|
left: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
background: var(--panel);
|
||||||
|
border: 1px solid var(--panel-border);
|
||||||
|
border-radius: 14px;
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-wrap .ol-visible-layers-extent button {
|
||||||
|
font-size: 1.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OpenLayers hides this control while the view is north-up. */
|
/* OpenLayers hides this control while the view is north-up. */
|
||||||
@@ -364,6 +412,11 @@ button:disabled {
|
|||||||
right: 12px;
|
right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.map-wrap .ol-visible-layers-extent {
|
||||||
|
top: 92px;
|
||||||
|
right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.map-wrap .ol-rotate {
|
.map-wrap .ol-rotate {
|
||||||
right: 12px;
|
right: 12px;
|
||||||
bottom: 12px;
|
bottom: 12px;
|
||||||
|
|||||||
Reference in New Issue
Block a user