Files
sake/build/resources/main/static/mobile/js/bottom-sheet.js

186 lines
6.0 KiB
JavaScript

const openSheetButtons = document.querySelectorAll(".open-sheet");
const sheets = document.querySelectorAll(".sheet");
let sheetHeight;
let currentSheet = null;
const sheetsMap = new Map();
let vh = window.innerHeight / 100;
const setSheetHeight = (value) => {
if (!currentSheet) return;
const sheetContents = currentSheet.querySelector(".contents");
sheetHeight = Math.max(0, Math.min(90, value));
sheetContents.style.height = `${sheetHeight * vh}px`;
};
const setIsSheetShown = (isShown) => {
if (!currentSheet) return;
currentSheet.setAttribute("aria-hidden", String(!isShown));
document.body.style.overflow = isShown ? "hidden" : "";
document.querySelector(".screen-wrap").classList.toggle("is-fixed", isShown);
if (!isShown) {
currentSheet = null;
}
};
const throttle = (func, limit) => {
let lastFunc;
let lastRan;
return function (...args) {
const context = this;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function () {
if (Date.now() - lastRan >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
};
const initializeSheet = (sheet, openButtons) => {
const sheetContents = sheet.querySelector(".contents");
const draggableArea = sheet.querySelector(".draggable-area");
// 버튼 클릭 시 시트 열기
openButtons.forEach((openButton) => {
openButton.addEventListener("click", () => {
currentSheet = sheet;
setSheetHeight(Math.min(50, (720 / window.innerHeight) * 100));
setIsSheetShown(true);
});
});
// 닫기 버튼 클릭 시 시트 닫기
sheet.querySelector(".close-sheet").addEventListener("click", () => {
setIsSheetShown(false);
});
// 배경 클릭 시 시트 닫기
sheet.querySelector(".overlay").addEventListener("click", () => {
setIsSheetShown(false);
});
// 드래그 이벤트
const touchPosition = (event) => (event.touches ? event.touches[0] : event);
let dragPosition;
const onDragStart = (event) => {
currentSheet = sheet;
dragPosition = touchPosition(event).pageY;
sheetContents.classList.add("not-selectable");
draggableArea.style.cursor = document.body.style.cursor = "grabbing";
window.addEventListener("mousemove", onDragMove);
window.addEventListener("touchmove", onDragMove, { passive: false });
window.addEventListener("mouseup", onDragEnd);
window.addEventListener("touchend", onDragEnd);
};
// const onDragMove = (event) => {
// if (dragPosition === undefined || !currentSheet) return;
// event.preventDefault();
// const y = touchPosition(event).pageY;
// const deltaY = dragPosition - y;
// const deltaHeight = (deltaY / window.innerHeight) * 100;
// setSheetHeight(sheetHeight + deltaHeight);
// dragPosition = y;
// };
const onDragMove = throttle((event) => {
if (dragPosition === undefined || !currentSheet) return;
event.preventDefault();
const y = touchPosition(event).pageY;
const deltaY = dragPosition - y;
const deltaHeight = (deltaY / window.innerHeight) * 100;
setSheetHeight(sheetHeight + deltaHeight);
dragPosition = y;
}, 25);
const onDragEnd = () => {
dragPosition = undefined;
if (currentSheet) {
const sheetContents = currentSheet.querySelector(".contents");
sheetContents.classList.remove("not-selectable");
draggableArea.style.cursor = document.body.style.cursor = "";
if (sheetHeight < 45) {
setIsSheetShown(false);
return;
} else if (
sheetHeight > 55 &&
sheetHeight < 85 &&
!sheetContents.classList.contains("fullscreen")
) {
setSheetHeight(90);
sheetContents.classList.add("fullscreen");
return;
} else if (sheetHeight < 85 && sheetContents.classList.contains("fullscreen")) {
setSheetHeight(50);
sheetContents.classList.remove("fullscreen");
return;
} else if (sheetHeight === 90) {
return;
} else if (sheetHeight > 85) {
setSheetHeight(90);
sheetContents.classList.add("fullscreen");
return;
} else if (sheetHeight < 85) {
setSheetHeight(50);
sheetContents.classList.remove("fullscreen");
}
}
window.removeEventListener("mousemove", onDragMove);
window.removeEventListener("touchmove", onDragMove);
window.removeEventListener("mouseup", onDragEnd);
window.removeEventListener("touchend", onDragEnd);
};
draggableArea.addEventListener("mousedown", onDragStart);
draggableArea.addEventListener("touchstart", onDragStart, { passive: false });
};
// 버튼의 data-sheet-target와 일치하는 시트를 찾아서 sheetsMap에 추가
openSheetButtons.forEach((button) => {
const sheetId = button.dataset.sheetTarget;
const sheet = document.getElementById(sheetId);
if (sheet) {
if (!sheetsMap.has(sheet)) {
sheetsMap.set(sheet, []);
}
sheetsMap.get(sheet).push(button);
}
});
// 각 시트를 초기화
sheetsMap.forEach((buttons, sheet) => {
initializeSheet(sheet, buttons);
});
// esc 키로 바텀시트 닫기
window.addEventListener("keyup", (event) => {
if (currentSheet && document.activeElement !== currentSheet) {
const isSheetElementFocused =
currentSheet.contains(event.target) && document.activeElement === event.target;
if (event.key === "Escape" && !isSheetElementFocused) {
setIsSheetShown(false);
}
}
});