/** * HUMEN - 파묘 서비스 메인 JavaScript (jQuery 기반) * jQuery CDN: https://code.jquery.com/jquery-3.7.1.min.js */ $(function () { /* ===================================================== 헤더 스크롤 효과 ===================================================== */ var $header = $('.site-header'); $(window).on('scroll.header', function () { if ($(this).scrollTop() > 50) { $header.addClass('scrolled'); } else { $header.removeClass('scrolled'); } }); /* ===================================================== 모바일 햄버거 메뉴 (독립 오버레이 방식) 구조: #mobile-nav : 우측 슬라이드 패널 #mobile-nav-overlay : 반투명 배경 #menu-toggle : 헤더 햄버거 버튼 #mobile-nav-close : 패널 내 ✕ 버튼 .mnav-link : 상위 메뉴 링크 (클릭 시 이동 + 메뉴 닫기) .mnav-toggle : 하위 메뉴 펼침 버튼 (▾, 페이지 이동 없음) .mnav-submenu : 하위 메뉴 컨테이너 .mnav-sublink : 하위 메뉴 링크 (클릭 시 이동 + 메뉴 닫기) ===================================================== */ var $mobileNav = $('#mobile-nav'); var $overlay = $('#mobile-nav-overlay'); var $menuToggle = $('#menu-toggle'); var $mobileClose = $('#mobile-nav-close'); var mobileOpen = false; function openMobileMenu() { mobileOpen = true; $mobileNav.show(); $overlay.show(); $('body').css('overflow', 'hidden'); $menuToggle.addClass('active').attr('aria-label', '메뉴 닫기'); } function closeMobileMenu() { mobileOpen = false; $mobileNav.hide(); $overlay.hide(); $('body').css('overflow', ''); $menuToggle.removeClass('active').attr('aria-label', '메뉴 열기'); // 열려있는 서브메뉴 모두 닫기 $('.mnav-submenu').hide(); $('.mnav-toggle').css('transform', '').text('▾'); } // 햄버거 버튼 클릭 $menuToggle.on('click', function (e) { e.stopPropagation(); mobileOpen ? closeMobileMenu() : openMobileMenu(); }); // 패널 내 ✕ 버튼 클릭 $mobileClose.on('click', function () { closeMobileMenu(); }); // 반투명 배경 클릭 시 닫기 $overlay.on('click', function () { closeMobileMenu(); }); // ESC 키로 닫기 $(document).on('keydown.mobilemenu', function (e) { if (e.key === 'Escape' && mobileOpen) closeMobileMenu(); }); // ▾ 토글 버튼: 서브메뉴 펼침/접음 (페이지 이동 없음) $mobileNav.on('click', '.mnav-toggle', function (e) { e.preventDefault(); e.stopPropagation(); var $btn = $(this); var $item = $btn.closest('.mnav-item'); var $submenu = $item.find('.mnav-submenu'); var isOpen = $submenu.is(':visible'); // 다른 서브메뉴 모두 닫기 $('.mnav-submenu').not($submenu).slideUp(200); $('.mnav-toggle').not($btn).text('▾').css('transform', ''); if (isOpen) { $submenu.slideUp(200); $btn.text('▾').css('transform', ''); } else { $submenu.slideDown(200); $btn.text('▴').css('color', '#c9a227'); } }); // 상위 메뉴 링크(.mnav-link) 클릭: 메뉴 닫고 이동 $mobileNav.on('click', '.mnav-link', function () { closeMobileMenu(); // 기본 href 이동은 브라우저가 처리 }); // 하위 메뉴 링크(.mnav-sublink) 클릭: 메뉴 닫고 이동 $mobileNav.on('click', '.mnav-sublink', function () { closeMobileMenu(); // 기본 href 이동은 브라우저가 처리 }); // 화면 크기 변경 시 모바일 메뉴 초기화 $(window).on('resize.mobilemenu', function () { if ($(this).width() >= 769 && mobileOpen) { closeMobileMenu(); } }); /* ===================================================== 히어로 슬라이더 ===================================================== */ var $slides = $('.hero-slide'); var $dots = $('.slider-dot'); var current = 0; var slideTimer = null; function goToSlide(index) { $slides.removeClass('active'); $dots.removeClass('active'); current = (index + $slides.length) % $slides.length; $slides.eq(current).addClass('active'); $dots.eq(current).addClass('active'); } if ($slides.length) { goToSlide(0); slideTimer = setInterval(function () { goToSlide(current + 1); }, 5000); $dots.on('click', function () { clearInterval(slideTimer); goToSlide($(this).index()); slideTimer = setInterval(function () { goToSlide(current + 1); }, 5000); }); } /* ===================================================== 스크롤 탑 버튼 ===================================================== */ var $scrollTop = $('.scroll-top'); $(window).on('scroll.scrolltop', function () { if ($(this).scrollTop() > 400) { $scrollTop.addClass('visible'); } else { $scrollTop.removeClass('visible'); } }); $scrollTop.on('click', function () { $('html, body').animate({ scrollTop: 0 }, 400); }); /* ===================================================== 탭 컴포넌트 ===================================================== */ $(document).on('click', '.tab-btn', function () { var $btn = $(this); var tabId = $btn.data('tab'); var $container = $btn.closest('.tabs'); $container.find('.tab-btn').removeClass('active'); $container.find('.tab-content').removeClass('active'); $btn.addClass('active'); $container.find('#' + tabId).addClass('active'); }); /* ===================================================== 아코디언 ===================================================== */ $(document).on('click', '.accordion-header', function () { var $hdr = $(this); var $body = $hdr.next('.accordion-body'); var isActive = $hdr.hasClass('active'); var $accordion = $hdr.closest('.accordion'); $accordion.find('.accordion-header').removeClass('active'); $accordion.find('.accordion-body').removeClass('open'); if (!isActive) { $hdr.addClass('active'); $body.addClass('open'); } }); /* ===================================================== 스크롤 애니메이션 (IntersectionObserver) ===================================================== */ if ('IntersectionObserver' in window) { var animObserver = new IntersectionObserver(function (entries) { $.each(entries, function (_, entry) { if (entry.isIntersecting) { $(entry.target).addClass('animate-in'); animObserver.unobserve(entry.target); } }); }, { threshold: 0.15 }); $('[data-animate]').each(function () { animObserver.observe(this); }); } /* ===================================================== 숫자 카운터 애니메이션 ===================================================== */ if ('IntersectionObserver' in window) { var counterObserver = new IntersectionObserver(function (entries) { $.each(entries, function (_, entry) { if (entry.isIntersecting) { var $el = $(entry.target); var target = parseInt($el.data('count'), 10); var suffix = $el.data('suffix') || ''; var start = Date.now(); var duration = 2000; (function tick() { var elapsed = Date.now() - start; var progress = Math.min(elapsed / duration, 1); var eased = 1 - Math.pow(1 - progress, 3); $el.text(Math.floor(eased * target).toLocaleString() + suffix); if (progress < 1) requestAnimationFrame(tick); })(); counterObserver.unobserve(entry.target); } }); }, { threshold: 0.5 }); $('.stat-number[data-count]').each(function () { counterObserver.observe(this); }); } /* ===================================================== 문의 폼 처리 ===================================================== */ $('#contact-form').on('submit', function (e) { e.preventDefault(); var $btn = $(this).find('.form-submit'); var origText = $btn.text(); $btn.text('전송 중...').prop('disabled', true); setTimeout(function () { $btn.text('✓ 문의가 접수되었습니다').css('background', '#27ae60'); setTimeout(function () { $btn.text(origText).css('background', '').prop('disabled', false); $('#contact-form')[0].reset(); }, 3000); }, 1500); }); /* ===================================================== 부드러운 앵커 스크롤 ===================================================== */ $(document).on('click', 'a[href^="#"]', function (e) { var targetId = $(this).attr('href').slice(1); if (!targetId) return; var $target = $('#' + targetId); if (!$target.length) return; e.preventDefault(); var headerH = $header.length ? $header.outerHeight() : 0; var targetPos = $target.offset().top - headerH - 20; $('html, body').animate({ scrollTop: targetPos }, 400); if (mobileOpen) closeMobileMenu(); }); /* ===================================================== 현재 페이지 네비게이션 활성화 ===================================================== */ var currentPath = window.location.pathname; $('.nav-link, .dropdown-item').each(function () { var href = $(this).attr('href'); if (href && href !== '#' && currentPath.indexOf(href.replace('.html', '')) !== -1) { $(this).addClass('active'); } }); });