267 lines
8.6 KiB
JavaScript
267 lines
8.6 KiB
JavaScript
/**
|
|
* intro-init.js
|
|
* 인트로 페이지 초기화
|
|
* 공통 모듈 활용 (ErrorHandler, DOMUtils, Utils, EventManager)
|
|
*/
|
|
|
|
// 전역 의존성 (폴백 포함)
|
|
const _initDomUtils = typeof DOMUtils !== 'undefined' ? DOMUtils : null;
|
|
const _initErrorHandler = typeof ErrorHandler !== 'undefined' ? ErrorHandler : null;
|
|
const _initUtils = typeof Utils !== 'undefined' ? Utils : null;
|
|
const _initEventManager = typeof eventManager !== 'undefined' ? eventManager : null;
|
|
|
|
/**
|
|
* 에러 처리 헬퍼
|
|
* @private
|
|
*/
|
|
function _handleError(error, context, additionalInfo = {}) {
|
|
if (_initErrorHandler) {
|
|
_initErrorHandler.handle(error, {
|
|
context: `IntroInit.${context}`,
|
|
component: 'IntroInit',
|
|
...additionalInfo
|
|
}, false);
|
|
} else {
|
|
console.error(`[IntroInit] ${context}:`, error, additionalInfo);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 페이지 초기 설정
|
|
*/
|
|
function initializeIntroPage() {
|
|
try {
|
|
// DOM 요소 선택
|
|
const cardsContainer = _initDomUtils?.$("#cardsContainer") || document.getElementById("cardsContainer");
|
|
const ctaBtn = _initDomUtils?.$("#ctaBtn") || document.getElementById("ctaBtn");
|
|
const maskContainer = _initDomUtils?.$("#maskContainer") || document.getElementById("maskContainer");
|
|
const typedNameEl = _initDomUtils?.$("#typedName") || document.getElementById("typedName");
|
|
const cursorEl = _initDomUtils?.$("#cursor") || document.getElementById("cursor");
|
|
|
|
// 초기 요소 숨김 처리
|
|
if (cardsContainer) {
|
|
if (_initDomUtils && _initDomUtils.setStyles) {
|
|
_initDomUtils.setStyles(cardsContainer, { display: 'none' });
|
|
} else {
|
|
cardsContainer.style.display = "none";
|
|
}
|
|
} else {
|
|
console.warn('[IntroInit] cardsContainer 요소를 찾을 수 없습니다.');
|
|
}
|
|
|
|
if (ctaBtn) {
|
|
if (_initDomUtils && _initDomUtils.setStyles) {
|
|
_initDomUtils.setStyles(ctaBtn, { display: 'none' });
|
|
} else {
|
|
ctaBtn.style.display = "none";
|
|
}
|
|
} else {
|
|
console.warn('[IntroInit] ctaBtn 요소를 찾을 수 없습니다.');
|
|
}
|
|
|
|
if (maskContainer) {
|
|
maskContainer.style.setProperty("--size", "30px");
|
|
} else {
|
|
console.warn('[IntroInit] maskContainer 요소를 찾을 수 없습니다.');
|
|
}
|
|
|
|
// 이벤트 리스너 등록
|
|
if (typeof initEventListeners === 'function') {
|
|
try {
|
|
initEventListeners();
|
|
} catch (error) {
|
|
_handleError(error, 'initializeIntroPage.initEventListeners');
|
|
}
|
|
} else {
|
|
console.warn('[IntroInit] initEventListeners 함수를 찾을 수 없습니다.');
|
|
}
|
|
|
|
// typedIndex 초기화 및 typedName 요소 초기화
|
|
if (typeof INTRO_STATE !== 'undefined') {
|
|
INTRO_STATE.typedIndex = 0;
|
|
} else {
|
|
console.warn('[IntroInit] INTRO_STATE가 정의되지 않았습니다.');
|
|
}
|
|
|
|
if (typedNameEl) {
|
|
typedNameEl.textContent = "";
|
|
} else {
|
|
console.warn('[IntroInit] typedName 요소를 찾을 수 없습니다.');
|
|
}
|
|
|
|
if (cursorEl) {
|
|
if (_initDomUtils && _initDomUtils.setStyles) {
|
|
_initDomUtils.setStyles(cursorEl, { opacity: '1' });
|
|
} else {
|
|
cursorEl.style.opacity = "1";
|
|
}
|
|
} else {
|
|
console.warn('[IntroInit] cursor 요소를 찾을 수 없습니다.');
|
|
}
|
|
|
|
// 타이핑 애니메이션 시작 (INTRO_CONFIG가 준비된 후)
|
|
const animationDelay = 800;
|
|
const delayFn = _initUtils && _initUtils.delay ? _initUtils.delay : (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
delayFn(animationDelay).then(() => {
|
|
try {
|
|
if (typeof INTRO_CONFIG !== 'undefined' && typeof INTRO_STATE !== 'undefined' && INTRO_CONFIG.fullName) {
|
|
// text-ani 섹션 표시 (CSS에서 display: none이므로 animating 클래스 추가)
|
|
const textAniSection = _initDomUtils?.$('.text-ani') || document.querySelector('.text-ani');
|
|
if (textAniSection) {
|
|
if (_initDomUtils && _initDomUtils.addClasses) {
|
|
_initDomUtils.addClasses(textAniSection, 'animating');
|
|
} else {
|
|
textAniSection.classList.add('animating');
|
|
}
|
|
}
|
|
|
|
INTRO_STATE.typedIndex = 0;
|
|
|
|
if (typeof typeName === 'function') {
|
|
typeName();
|
|
} else {
|
|
console.warn('[IntroInit] typeName 함수를 찾을 수 없습니다.');
|
|
}
|
|
} else {
|
|
console.warn('[IntroInit] INTRO_CONFIG 또는 INTRO_STATE가 준비되지 않았거나 fullName이 없습니다.');
|
|
}
|
|
} catch (error) {
|
|
_handleError(error, 'initializeIntroPage.animationStart');
|
|
}
|
|
});
|
|
} catch (error) {
|
|
_handleError(error, 'initializeIntroPage');
|
|
}
|
|
}
|
|
|
|
// DOM이 로드되면 초기화 실행
|
|
function setupInitialization() {
|
|
try {
|
|
if (document.readyState === "loading") {
|
|
// EventManager를 사용하여 이벤트 등록 (폴백 포함)
|
|
if (_initEventManager) {
|
|
_initEventManager.once(document, "DOMContentLoaded", initializeIntroPage);
|
|
} else {
|
|
document.addEventListener("DOMContentLoaded", initializeIntroPage, { once: true });
|
|
}
|
|
} else {
|
|
// DOMContentLoaded 이벤트가 이미 발생한 경우
|
|
initializeIntroPage();
|
|
}
|
|
} catch (error) {
|
|
_handleError(error, 'setupInitialization');
|
|
// 폴백: 에러가 발생해도 초기화 시도
|
|
if (document.readyState !== "loading") {
|
|
initializeIntroPage();
|
|
}
|
|
}
|
|
}
|
|
|
|
setupInitialization();
|
|
|
|
/**
|
|
* 외부에서 사용자 이름을 설정하고 다시 시작하는 함수
|
|
* @param {string} name - 사용자 이름
|
|
*/
|
|
function restartIntroWithName(name) {
|
|
try {
|
|
// 입력 검증
|
|
if (typeof name !== 'string' || name.trim() === '') {
|
|
_handleError(new Error('유효하지 않은 사용자 이름'), 'restartIntroWithName', { name });
|
|
return;
|
|
}
|
|
|
|
if (typeof INTRO_STATE === 'undefined') {
|
|
_handleError(new Error('INTRO_STATE가 정의되지 않았습니다'), 'restartIntroWithName');
|
|
return;
|
|
}
|
|
|
|
// 이름 설정
|
|
if (typeof setUserName === 'function') {
|
|
try {
|
|
setUserName(name);
|
|
} catch (error) {
|
|
_handleError(error, 'restartIntroWithName.setUserName');
|
|
}
|
|
} else {
|
|
console.warn('[IntroInit] setUserName 함수를 찾을 수 없습니다.');
|
|
}
|
|
|
|
// 상태 초기화
|
|
INTRO_STATE.currentSection = 0;
|
|
INTRO_STATE.typedIndex = 0;
|
|
INTRO_STATE.isScrolling = false;
|
|
INTRO_STATE.isAnimating = false;
|
|
INTRO_STATE.section2AnimDone = false;
|
|
clearTimeout(INTRO_STATE.autoScrollTimer);
|
|
INTRO_STATE.lastInteractionTime = Date.now();
|
|
|
|
// DOM 요소 선택
|
|
const typedNameEl = _initDomUtils?.$("#typedName") || document.getElementById("typedName");
|
|
const cursorEl = _initDomUtils?.$("#cursor") || document.getElementById("cursor");
|
|
const welcomeEl = _initDomUtils?.$("#welcome") || document.getElementById("welcome");
|
|
const textAniSection = _initDomUtils?.$('.text-ani') || document.querySelector('.text-ani');
|
|
|
|
// 화면 리셋
|
|
if (typedNameEl) {
|
|
typedNameEl.textContent = "";
|
|
} else {
|
|
console.warn('[IntroInit] typedName 요소를 찾을 수 없습니다.');
|
|
}
|
|
|
|
if (cursorEl) {
|
|
if (_initDomUtils && _initDomUtils.setStyles) {
|
|
_initDomUtils.setStyles(cursorEl, { opacity: '1' });
|
|
} else {
|
|
cursorEl.style.opacity = "1";
|
|
}
|
|
} else {
|
|
console.warn('[IntroInit] cursor 요소를 찾을 수 없습니다.');
|
|
}
|
|
|
|
if (welcomeEl) {
|
|
welcomeEl.innerHTML = "";
|
|
} else {
|
|
console.warn('[IntroInit] welcome 요소를 찾을 수 없습니다.');
|
|
}
|
|
|
|
// text-ani 섹션 표시
|
|
if (textAniSection) {
|
|
if (_initDomUtils && _initDomUtils.addClasses) {
|
|
_initDomUtils.addClasses(textAniSection, 'animating');
|
|
} else {
|
|
textAniSection.classList.add('animating');
|
|
}
|
|
}
|
|
|
|
// 섹션 1로 이동
|
|
if (typeof goToSection === 'function') {
|
|
try {
|
|
goToSection(0);
|
|
} catch (error) {
|
|
_handleError(error, 'restartIntroWithName.goToSection');
|
|
}
|
|
} else {
|
|
console.warn('[IntroInit] goToSection 함수를 찾을 수 없습니다.');
|
|
}
|
|
|
|
// 타이핑 재시작
|
|
const animationDelay = 800;
|
|
const delayFn = _initUtils && _initUtils.delay ? _initUtils.delay : (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
delayFn(animationDelay).then(() => {
|
|
try {
|
|
if (typeof typeName === 'function') {
|
|
typeName();
|
|
} else {
|
|
console.warn('[IntroInit] typeName 함수를 찾을 수 없습니다.');
|
|
}
|
|
} catch (error) {
|
|
_handleError(error, 'restartIntroWithName.typeName');
|
|
}
|
|
});
|
|
} catch (error) {
|
|
_handleError(error, 'restartIntroWithName');
|
|
}
|
|
} |