Initial commit: 교육 프로젝트 배포

This commit is contained in:
송대일
2026-07-01 18:32:42 +09:00
commit be6dccd120
1483 changed files with 5082202 additions and 0 deletions
+162
View File
@@ -0,0 +1,162 @@
/**
* intro-events.js
* 이벤트 리스너 설정
*/
/**
* 모든 이벤트 리스너 등록
*/
function initEventListeners() {
// 마우스 휠 이벤트
document.addEventListener("wheel", (e) => {
resetAutoScrollTimer();
if (e.deltaY > 0) handleScrollDown();
else handleScrollUp();
});
// 터치 이벤트
let touchStartY = 0;
document.addEventListener(
"touchstart",
(e) => {
touchStartY = e.touches[0].clientY;
resetAutoScrollTimer();
},
{ passive: true }
);
document.addEventListener(
"touchend",
(e) => {
const diff = touchStartY - e.changedTouches[0].clientY;
if (Math.abs(diff) > 60) {
if (diff > 0) handleScrollDown();
else handleScrollUp();
}
},
{ passive: true }
);
// 키보드 이벤트
document.addEventListener("keydown", (e) => {
if (["ArrowDown", "PageDown", " "].includes(e.key)) {
e.preventDefault();
resetAutoScrollTimer();
handleScrollDown();
} else if (["ArrowUp", "PageUp"].includes(e.key)) {
e.preventDefault();
resetAutoScrollTimer();
handleScrollUp();
}
});
// 마우스 움직임 이벤트 (Section 3 마스크 효과)
// requestAnimationFrame을 사용하여 부드러운 업데이트 보장
let rafId = null;
let lastMouseEvent = null;
document.addEventListener("mousemove", (e) => {
if (typeof INTRO_STATE !== 'undefined' && INTRO_STATE.currentSection === 2) {
// 마지막 마우스 이벤트 저장
lastMouseEvent = e;
// 이미 요청된 애니메이션 프레임이 없으면 새로 요청
if (rafId === null) {
rafId = requestAnimationFrame(() => {
if (lastMouseEvent) {
handleMouseMoveOnSection3(lastMouseEvent);
}
rafId = null;
lastMouseEvent = null;
});
}
}
});
}
/**
* Section 3의 마우스 움직임 처리 (마스크 효과)
* @param {MouseEvent} e - 마우스 이벤트
*/
function handleMouseMoveOnSection3(e) {
try {
// 입력 검증
if (!e || typeof e.clientX !== 'number' || typeof e.clientY !== 'number') {
return;
}
const maskContainer = document.getElementById("maskContainer");
if (!maskContainer) {
return; // 요소가 없으면 조용히 종료
}
const mouseX = e.clientX;
const mouseY = e.clientY;
const mainContainer = document.getElementById("mainContainer");
if (!mainContainer) {
return;
}
const mainContainerRect = mainContainer.getBoundingClientRect();
const h1Elements = mainContainer.querySelectorAll("p");
const ctaBtn = document.querySelector(".cta-btn");
let hovering = false;
let isCtaBtnHovering = false;
// .cta-btn 위에 마우스가 있는지 먼저 체크
if (ctaBtn) {
try {
const ctaRect = ctaBtn.getBoundingClientRect();
if (
mouseX >= ctaRect.left &&
mouseX <= ctaRect.right &&
mouseY >= ctaRect.top &&
mouseY <= ctaRect.bottom
) {
hovering = true;
isCtaBtnHovering = true;
}
} catch (error) {
console.warn('[IntroEvents] CTA 버튼 체크 중 오류:', error);
}
}
// p 요소들 체크
try {
h1Elements.forEach((element) => {
try {
const h1Rect = element.getBoundingClientRect();
if (
mouseX >= h1Rect.left &&
mouseX <= h1Rect.right &&
mouseY >= h1Rect.top &&
mouseY <= h1Rect.bottom
) {
hovering = true;
}
} catch (error) {
// 개별 요소 체크 실패는 무시
}
});
} catch (error) {
console.warn('[IntroEvents] 요소 체크 중 오류:', error);
}
// .cta-btn 위에 있을 때만 세로 위치 고정, 그 외에는 마우스 위치 따라감
const targetY = isCtaBtnHovering
? mainContainerRect.top + mainContainerRect.height / 2.3
: mouseY;
// CSS 변수 설정 (안전하게)
const x = Math.max(0, Math.min(mouseX, window.innerWidth));
const y = Math.max(0, Math.min(targetY, window.innerHeight));
const targetSize = hovering ? 380 : 30;
maskContainer.style.setProperty("--x", `${x}px`);
maskContainer.style.setProperty("--y", `${y}px`);
maskContainer.style.setProperty("--size", `${targetSize}px`);
} catch (error) {
console.error('[IntroEvents] handleMouseMoveOnSection3 오류:', error);
}
}