186 lines
6.0 KiB
JavaScript
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);
|
|
}
|
|
}
|
|
});
|