feat: add area zoom map control
This commit is contained in:
@@ -72,12 +72,21 @@ const parcelSearchLayer = new ol.layer.Vector({
|
||||
}),
|
||||
});
|
||||
|
||||
const areaZoomInteraction = new ol.interaction.DragBox({
|
||||
className: "ol-area-zoom-box",
|
||||
condition: ol.events.condition.primaryAction,
|
||||
minArea: 16,
|
||||
});
|
||||
areaZoomInteraction.setActive(false);
|
||||
let areaZoomButton;
|
||||
|
||||
const map = new ol.Map({
|
||||
target: "map",
|
||||
controls: ol.control
|
||||
.defaults.defaults({ rotate: false })
|
||||
.extend([
|
||||
createVisibleLayersExtentControl(),
|
||||
createAreaZoomControl(),
|
||||
new ol.control.Rotate({
|
||||
autoHide: true,
|
||||
label: createNorthPointerIcon(),
|
||||
@@ -90,6 +99,7 @@ const map = new ol.Map({
|
||||
zoom: 7,
|
||||
}),
|
||||
});
|
||||
map.addInteraction(areaZoomInteraction);
|
||||
|
||||
let availableLayers = [];
|
||||
let selectedLayers = [];
|
||||
@@ -108,12 +118,25 @@ document.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape") {
|
||||
if (!els.featureModal.hidden) {
|
||||
closeFeatureModal();
|
||||
} else if (areaZoomInteraction.getActive()) {
|
||||
setAreaZoomMode(false);
|
||||
} else if (!els.appShell.classList.contains("sidebar-is-collapsed")) {
|
||||
setSidebarCollapsed(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
map.on("singleclick", showFeatureInformation);
|
||||
areaZoomInteraction.on("boxend", zoomToSelectedArea);
|
||||
areaZoomInteraction.on("boxcancel", () => {
|
||||
// A click or a very short drag is not a selection. Exit on the next frame so
|
||||
// cancelling a drag while disabling the interaction cannot recursively
|
||||
// trigger another cancellation.
|
||||
requestAnimationFrame(() => {
|
||||
if (areaZoomInteraction.getActive()) {
|
||||
setAreaZoomMode(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
loadLayers();
|
||||
|
||||
@@ -150,6 +173,57 @@ function createVisibleLayersExtentControl() {
|
||||
return new ol.control.Control({ element });
|
||||
}
|
||||
|
||||
function createAreaZoomControl() {
|
||||
const element = document.createElement("div");
|
||||
element.className = "ol-area-zoom ol-unselectable ol-control";
|
||||
|
||||
const button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.title = "Zoom to area";
|
||||
button.setAttribute("aria-label", "Zoom to area");
|
||||
button.setAttribute("aria-pressed", "false");
|
||||
|
||||
const icon = document.createElement("img");
|
||||
icon.className = "area-zoom-icon";
|
||||
icon.src = "./assets/icons/area-zoom.svg";
|
||||
icon.alt = "";
|
||||
button.append(icon);
|
||||
|
||||
button.addEventListener("click", () => setAreaZoomMode(!areaZoomInteraction.getActive()));
|
||||
element.append(button);
|
||||
areaZoomButton = button;
|
||||
|
||||
return new ol.control.Control({ element });
|
||||
}
|
||||
|
||||
function setAreaZoomMode(active) {
|
||||
areaZoomInteraction.setActive(active);
|
||||
map.getViewport().classList.toggle("area-zoom-is-active", active);
|
||||
areaZoomButton?.setAttribute("aria-pressed", String(active));
|
||||
areaZoomButton?.setAttribute(
|
||||
"title",
|
||||
active ? "Exit area zoom (Esc)" : "Zoom to area",
|
||||
);
|
||||
|
||||
if (active) {
|
||||
closeFeatureModal();
|
||||
}
|
||||
}
|
||||
|
||||
function zoomToSelectedArea() {
|
||||
const extent = areaZoomInteraction.getGeometry()?.getExtent();
|
||||
|
||||
if (extent && extent.every(Number.isFinite)) {
|
||||
map.getView().fit(extent, {
|
||||
padding: [64, 64, 64, 64],
|
||||
duration: 500,
|
||||
maxZoom: 19,
|
||||
});
|
||||
}
|
||||
|
||||
setAreaZoomMode(false);
|
||||
}
|
||||
|
||||
async function searchParcela(event) {
|
||||
event.preventDefault();
|
||||
|
||||
@@ -328,6 +402,10 @@ function syncSelectedLayers() {
|
||||
}
|
||||
|
||||
async function showFeatureInformation(event) {
|
||||
if (areaZoomInteraction.getActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const queryLayers = availableLayers
|
||||
.map((layer) => layer.name)
|
||||
.filter(
|
||||
|
||||
Reference in New Issue
Block a user