feat: allow dragging feature dialog
This commit is contained in:
@@ -7,6 +7,7 @@ const FEATURE_INFO_LAYER_NAMES = new Set(["parcelas", "predios"]);
|
||||
const DEVICE_ORIENTATION_EVENTS = ["deviceorientationabsolute", "deviceorientation"];
|
||||
const COMPASS_HEADING_DEADBAND = 2;
|
||||
const SMALL_SCREEN_MEDIA_QUERY = "(max-width: 920px)";
|
||||
const MODAL_VIEWPORT_PADDING = 24;
|
||||
|
||||
const els = {
|
||||
appShell: document.querySelector(".app-shell"),
|
||||
@@ -21,6 +22,7 @@ const els = {
|
||||
parcelSearchStatus: document.getElementById("parcel-search-status"),
|
||||
backgroundSelect: document.getElementById("background-select"),
|
||||
featureModal: document.getElementById("feature-modal"),
|
||||
featureModalDialog: document.querySelector(".feature-modal-dialog"),
|
||||
featureModalClose: document.getElementById("feature-modal-close"),
|
||||
featureModalKind: document.getElementById("feature-modal-kind"),
|
||||
featureArea: document.getElementById("feature-area"),
|
||||
@@ -108,6 +110,7 @@ let lastCompassHeading;
|
||||
let pendingCompassHeading;
|
||||
let compassAnimationFrame;
|
||||
let deviceCompassFallbackTimer;
|
||||
let modalDrag;
|
||||
|
||||
const map = new ol.Map({
|
||||
target: "map",
|
||||
@@ -148,6 +151,10 @@ els.backgroundSelect.addEventListener("change", syncBackground);
|
||||
els.sidebarOpen.addEventListener("click", () => setSidebarCollapsed(false));
|
||||
els.sidebarClose.addEventListener("click", () => setSidebarCollapsed(true));
|
||||
els.featureModalClose.addEventListener("click", closeFeatureModal);
|
||||
els.featureModalDialog.addEventListener("pointerdown", startFeatureModalDrag);
|
||||
els.featureModalDialog.addEventListener("pointermove", dragFeatureModal);
|
||||
els.featureModalDialog.addEventListener("pointerup", stopFeatureModalDrag);
|
||||
els.featureModalDialog.addEventListener("pointercancel", stopFeatureModalDrag);
|
||||
els.featureModal.addEventListener("click", (event) => {
|
||||
if (event.target.matches("[data-feature-modal-close]")) {
|
||||
closeFeatureModal();
|
||||
@@ -164,6 +171,7 @@ document.addEventListener("keydown", (event) => {
|
||||
}
|
||||
}
|
||||
});
|
||||
window.addEventListener("resize", keepFeatureModalInViewport);
|
||||
map.on("singleclick", showFeatureInformation);
|
||||
areaZoomInteraction.on("boxend", zoomToSelectedArea);
|
||||
areaZoomInteraction.on("boxcancel", () => {
|
||||
@@ -745,9 +753,75 @@ function unqualifiedLayerName(name) {
|
||||
}
|
||||
|
||||
function closeFeatureModal() {
|
||||
resetFeatureModalPosition();
|
||||
els.featureModal.hidden = true;
|
||||
}
|
||||
|
||||
function startFeatureModalDrag(event) {
|
||||
if (event.button !== 0 || event.target.closest("button, a, input, select, textarea, label")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dialogRect = els.featureModalDialog.getBoundingClientRect();
|
||||
els.featureModalDialog.style.position = "fixed";
|
||||
els.featureModalDialog.style.left = `${dialogRect.left}px`;
|
||||
els.featureModalDialog.style.top = `${dialogRect.top}px`;
|
||||
els.featureModalDialog.style.margin = "0";
|
||||
els.featureModalDialog.classList.add("is-dragging");
|
||||
modalDrag = {
|
||||
pointerId: event.pointerId,
|
||||
offsetX: event.clientX - dialogRect.left,
|
||||
offsetY: event.clientY - dialogRect.top,
|
||||
};
|
||||
els.featureModalDialog.setPointerCapture(event.pointerId);
|
||||
}
|
||||
|
||||
function dragFeatureModal(event) {
|
||||
if (!modalDrag || event.pointerId !== modalDrag.pointerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dialogRect = els.featureModalDialog.getBoundingClientRect();
|
||||
const maxLeft = Math.max(MODAL_VIEWPORT_PADDING, window.innerWidth - dialogRect.width - MODAL_VIEWPORT_PADDING);
|
||||
const maxTop = Math.max(MODAL_VIEWPORT_PADDING, window.innerHeight - dialogRect.height - MODAL_VIEWPORT_PADDING);
|
||||
const left = Math.min(maxLeft, Math.max(MODAL_VIEWPORT_PADDING, event.clientX - modalDrag.offsetX));
|
||||
const top = Math.min(maxTop, Math.max(MODAL_VIEWPORT_PADDING, event.clientY - modalDrag.offsetY));
|
||||
|
||||
els.featureModalDialog.style.left = `${left}px`;
|
||||
els.featureModalDialog.style.top = `${top}px`;
|
||||
}
|
||||
|
||||
function stopFeatureModalDrag(event) {
|
||||
if (!modalDrag || event.pointerId !== modalDrag.pointerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
els.featureModalDialog.releasePointerCapture(event.pointerId);
|
||||
els.featureModalDialog.classList.remove("is-dragging");
|
||||
modalDrag = undefined;
|
||||
}
|
||||
|
||||
function keepFeatureModalInViewport() {
|
||||
if (els.featureModal.hidden || !els.featureModalDialog.style.left) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dialogRect = els.featureModalDialog.getBoundingClientRect();
|
||||
const maxLeft = Math.max(MODAL_VIEWPORT_PADDING, window.innerWidth - dialogRect.width - MODAL_VIEWPORT_PADDING);
|
||||
const maxTop = Math.max(MODAL_VIEWPORT_PADDING, window.innerHeight - dialogRect.height - MODAL_VIEWPORT_PADDING);
|
||||
els.featureModalDialog.style.left = `${Math.min(maxLeft, Math.max(MODAL_VIEWPORT_PADDING, dialogRect.left))}px`;
|
||||
els.featureModalDialog.style.top = `${Math.min(maxTop, Math.max(MODAL_VIEWPORT_PADDING, dialogRect.top))}px`;
|
||||
}
|
||||
|
||||
function resetFeatureModalPosition() {
|
||||
modalDrag = undefined;
|
||||
els.featureModalDialog.classList.remove("is-dragging");
|
||||
els.featureModalDialog.style.removeProperty("position");
|
||||
els.featureModalDialog.style.removeProperty("left");
|
||||
els.featureModalDialog.style.removeProperty("top");
|
||||
els.featureModalDialog.style.removeProperty("margin");
|
||||
}
|
||||
|
||||
function formatFeatureArea(feature) {
|
||||
const properties = feature.properties || {};
|
||||
const areaEntry = Object.entries(properties).find(([name, value]) =>
|
||||
|
||||
Reference in New Issue
Block a user