fix : 메인페이지 반응형 수정
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -5,125 +5,6 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<th:block layout:fragment="contentFragment">
|
<th:block layout:fragment="contentFragment">
|
||||||
<!-- Hero Carousel Section -->
|
|
||||||
<!-- <section class="hero-carousel-section">-->
|
|
||||||
<!-- <!– Carousel Container –>-->
|
|
||||||
<!-- <div class="hero-carousel-container">-->
|
|
||||||
<!-- <div class="hero-carousel-track">-->
|
|
||||||
<!-- <!– Slide 1 –>-->
|
|
||||||
<!-- <div class="hero-slide active" data-slide="0">-->
|
|
||||||
<!-- <div class="hero-slide-content">-->
|
|
||||||
<!-- <div class="hero-text-content">-->
|
|
||||||
<!-- <div class="hero-text">-->
|
|
||||||
<!-- <p class="hero-subtitle">세상의 모든 서비스</p>-->
|
|
||||||
<!-- <h2 class="hero-title">DJBank API가<br>함께 합니다.</h2>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <a href="#" class="btn-hero-signup">회원가입하기 <i class="bi bi-chevron-right"></i></a>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="hero-image-content">-->
|
|
||||||
<!-- <!– Inline SVG Tech Illustration –>-->
|
|
||||||
<!-- <svg class="hero-illustration" viewBox="0 0 500 400" fill="none" xmlns="http://www.w3.org/2000/svg">-->
|
|
||||||
<!-- <circle cx="250" cy="200" r="160" fill="url(#hero-grad-1)" opacity="0.15" />-->
|
|
||||||
<!-- <rect x="120" y="80" width="260" height="240" rx="20" fill="#FFFFFF" stroke="#0049B4" stroke-width="6"-->
|
|
||||||
<!-- class="floating-slow" />-->
|
|
||||||
<!-- <rect x="150" y="120" width="200" height="30" rx="6" fill="#E9F9FF" />-->
|
|
||||||
<!-- <rect x="150" y="170" width="130" height="15" rx="4" fill="#0049B4" opacity="0.3" />-->
|
|
||||||
<!-- <rect x="150" y="200" width="160" height="15" rx="4" fill="#0049B4" opacity="0.3" />-->
|
|
||||||
<!-- <circle cx="320" cy="270" r="25" fill="#0049B4" />-->
|
|
||||||
<!-- <path d="M315 270L323 275L331 265" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round"-->
|
|
||||||
<!-- stroke-linejoin="round" />-->
|
|
||||||
<!-- <rect x="80" y="220" width="90" height="80" rx="12" fill="#008AE2" opacity="0.9"-->
|
|
||||||
<!-- class="floating-fast" />-->
|
|
||||||
<!-- <circle cx="125" cy="260" r="20" fill="#FFFFFF" opacity="0.2" />-->
|
|
||||||
<!-- </svg>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
|
|
||||||
<!-- <!– Slide 2 –>-->
|
|
||||||
<!-- <div class="hero-slide" data-slide="1">-->
|
|
||||||
<!-- <div class="hero-slide-content">-->
|
|
||||||
<!-- <div class="hero-text-content">-->
|
|
||||||
<!-- <div class="hero-text">-->
|
|
||||||
<!-- <p class="hero-subtitle">더 안전하고 완벽한 거래</p>-->
|
|
||||||
<!-- <h2 class="hero-title">광주은행 오픈 API<br>보안 솔루션</h2>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <a href="#" class="btn-hero-signup">개발 가이드 보기 <i class="bi bi-chevron-right"></i></a>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="hero-image-content">-->
|
|
||||||
<!-- <svg class="hero-illustration" viewBox="0 0 500 400" fill="none" xmlns="http://www.w3.org/2000/svg">-->
|
|
||||||
<!-- <circle cx="250" cy="200" r="160" fill="url(#hero-grad-2)" opacity="0.15" />-->
|
|
||||||
<!-- <path d="M250 80L370 130V240C370 310 250 360 250 360C250 360 130 310 130 240V130L250 80Z" fill="#FFFFFF"-->
|
|
||||||
<!-- stroke="#008AE2" stroke-width="6" class="floating-slow" />-->
|
|
||||||
<!-- <path d="M250 140V280M180 210H320" stroke="#0049B4" stroke-width="6" stroke-linecap="round"-->
|
|
||||||
<!-- opacity="0.2" />-->
|
|
||||||
<!-- <circle cx="250" cy="210" r="45" fill="#0049B4" />-->
|
|
||||||
<!-- <path d="M235 210L245 220L265 200" stroke="#FFFFFF" stroke-width="5" stroke-linecap="round"-->
|
|
||||||
<!-- stroke-linejoin="round" />-->
|
|
||||||
<!-- </svg>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
|
|
||||||
<!-- <!– Slide 3 –>-->
|
|
||||||
<!-- <div class="hero-slide" data-slide="2">-->
|
|
||||||
<!-- <div class="hero-slide-content">-->
|
|
||||||
<!-- <div class="hero-text-content">-->
|
|
||||||
<!-- <div class="hero-text">-->
|
|
||||||
<!-- <p class="hero-subtitle">상상하는 금융의 구현</p>-->
|
|
||||||
<!-- <h2 class="hero-title">기업의 비즈니스를<br>혁신합니다.</h2>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <a href="#" class="btn-hero-signup">제휴 문의하기 <i class="bi bi-chevron-right"></i></a>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="hero-image-content">-->
|
|
||||||
<!-- <svg class="hero-illustration" viewBox="0 0 500 400" fill="none" xmlns="http://www.w3.org/2000/svg">-->
|
|
||||||
<!-- <circle cx="250" cy="200" r="160" fill="url(#hero-grad-1)" opacity="0.15" />-->
|
|
||||||
<!-- <path d="M120 280L210 170L300 240L400 110" stroke="#0049B4" stroke-width="8" stroke-linecap="round"-->
|
|
||||||
<!-- stroke-linejoin="round" class="draw-line" />-->
|
|
||||||
<!-- <circle cx="120" cy="280" r="12" fill="#008AE2" />-->
|
|
||||||
<!-- <circle cx="210" cy="170" r="12" fill="#008AE2" />-->
|
|
||||||
<!-- <circle cx="300" cy="240" r="12" fill="#008AE2" />-->
|
|
||||||
<!-- <circle cx="400" cy="110" r="16" fill="#0049B4" class="pulsing" />-->
|
|
||||||
<!-- </svg>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
|
|
||||||
<!-- <!– Navigation Buttons –>-->
|
|
||||||
<!-- <button class="hero-nav-btn hero-nav-prev" id="heroPrevBtn" aria-label="이전 슬라이드">-->
|
|
||||||
<!-- <svg width="18" height="32" viewBox="0 0 18 32" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform: scaleX(-1);">-->
|
|
||||||
<!-- <path d="M2.17021 31.1127L-0.000440909 28.942L13.3853 15.5564L-0.000438653 2.17065L2.17021 4.76837e-07L17.7266 15.5564L2.17021 31.1127Z" fill="#0049B4"/>-->
|
|
||||||
<!-- </svg>-->
|
|
||||||
<!-- </button>-->
|
|
||||||
<!-- <button class="hero-nav-btn hero-nav-next" id="heroNextBtn" aria-label="다음 슬라이드">-->
|
|
||||||
<!-- <svg width="18" height="32" viewBox="0 0 18 32" fill="none" xmlns="http://www.w3.org/2000/svg">-->
|
|
||||||
<!-- <path d="M2.17021 31.1127L-0.000440909 28.942L13.3853 15.5564L-0.000438653 2.17065L2.17021 4.76837e-07L17.7266 15.5564L2.17021 31.1127Z" fill="#0049B4"/>-->
|
|
||||||
<!-- </svg>-->
|
|
||||||
<!-- </button>-->
|
|
||||||
|
|
||||||
<!-- <!– Carousel Indicators –>-->
|
|
||||||
<!-- <div class="hero-carousel-indicators">-->
|
|
||||||
<!-- <button class="hero-indicator active" data-slide-to="0" aria-label="슬라이드 1"></button>-->
|
|
||||||
<!-- <button class="hero-indicator" data-slide-to="1" aria-label="슬라이드 2"></button>-->
|
|
||||||
<!-- <button class="hero-indicator" data-slide-to="2" aria-label="슬라이드 3"></button>-->
|
|
||||||
|
|
||||||
<!-- <!– Auto Play Toggle Button –>-->
|
|
||||||
<!-- <button class="hero-autoplay-toggle" id="heroAutoplayToggle" aria-label="자동 재생 일시정지">-->
|
|
||||||
<!-- <!– Pause Icon (default) –>-->
|
|
||||||
<!-- <svg class="pause-icon active" width="12" height="14" viewBox="0 0 12 14" fill="none" xmlns="http://www.w3.org/2000/svg">-->
|
|
||||||
<!-- <path d="M8 14V0H12V14H8ZM0 14V0H4V14H0Z" fill="#1D1B20"/>-->
|
|
||||||
<!-- </svg>-->
|
|
||||||
|
|
||||||
<!-- <!– Play Icon –>-->
|
|
||||||
<!-- <svg class="play-icon" width="12" height="14" viewBox="0 0 12 14" fill="none" xmlns="http://www.w3.org/2000/svg">-->
|
|
||||||
<!-- <path d="M0 0V14L12 7L0 0Z" fill="#0049B4"/>-->
|
|
||||||
<!-- </svg>-->
|
|
||||||
<!-- </button>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </section>-->
|
|
||||||
<!-- HERO CAROUSEL SECTION -->
|
|
||||||
<section class="hero-carousel-section">
|
<section class="hero-carousel-section">
|
||||||
<div class="hero-carousel-container">
|
<div class="hero-carousel-container">
|
||||||
<div class="hero-carousel-track">
|
<div class="hero-carousel-track">
|
||||||
@@ -162,8 +43,6 @@
|
|||||||
<div class="hero-slide" data-slide="1">
|
<div class="hero-slide" data-slide="1">
|
||||||
<div class="hero-slide-content">
|
<div class="hero-slide-content">
|
||||||
<div class="hero-text-content">
|
<div class="hero-text-content">
|
||||||
|
|
||||||
|
|
||||||
<div class="hero-text">
|
<div class="hero-text">
|
||||||
<p class="hero-subtitle">문서는 상세하게, 연동은 확실하게</p>
|
<p class="hero-subtitle">문서는 상세하게, 연동은 확실하게</p>
|
||||||
<h2 class="hero-title">준비된 DJBank API로 <br>완벽한 서비스를 성공하세요.</h2>
|
<h2 class="hero-title">준비된 DJBank API로 <br>완벽한 서비스를 성공하세요.</h2>
|
||||||
@@ -307,6 +186,18 @@
|
|||||||
<div class="search-container">
|
<div class="search-container">
|
||||||
<div class="search-card-container" data-node-id="1:264">
|
<div class="search-card-container" data-node-id="1:264">
|
||||||
<!-- Left Side: Title -->
|
<!-- Left Side: Title -->
|
||||||
|
<div class="search-character-box">
|
||||||
|
<svg class="search-mascot" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="15" y="15" width="90" height="90" rx="45" fill="#FFFFFF" stroke="#0049B4" stroke-width="4" />
|
||||||
|
<circle cx="45" cy="50" r="7" fill="#0049B4" />
|
||||||
|
<circle cx="75" cy="50" r="7" fill="#0049B4" />
|
||||||
|
<path d="M40 75C40 75 50 85 60 85C70 85 80 75 80 75" stroke="#0049B4" stroke-width="4"
|
||||||
|
stroke-linecap="round" />
|
||||||
|
<path d="M90 20L105 35M20 90L5 105" stroke="#008AE2" stroke-width="3" stroke-linecap="round" />
|
||||||
|
<circle cx="102" cy="72" r="5" fill="#008AE2" />
|
||||||
|
<circle cx="18" cy="40" r="3" fill="#008AE2" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
<div class="search-card-left" data-node-id="1:297">
|
<div class="search-card-left" data-node-id="1:297">
|
||||||
<h2 class="search-card-title">원하는 API를<br>지금 검색해 보세요.</h2>
|
<h2 class="search-card-title">원하는 API를<br>지금 검색해 보세요.</h2>
|
||||||
</div>
|
</div>
|
||||||
@@ -458,53 +349,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- 지원 센터 섹션 -->
|
|
||||||
<!-- <section class="support-center">-->
|
|
||||||
<!-- <div class="support-background"></div>-->
|
|
||||||
<!-- <div class="container">-->
|
|
||||||
<!-- <div class="section-header">-->
|
|
||||||
<!-- <h2 class="section-title">-->
|
|
||||||
<!-- <span class="title-regular">비지니스의 시작,</span><br>-->
|
|
||||||
<!-- <span class="title-bold">DJBank 오픈 API가 함께 하겠습니다.</span>-->
|
|
||||||
<!-- </h2>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="support-grid">-->
|
|
||||||
<!-- <!– 공지사항 카드 (50% width) –>-->
|
|
||||||
<!-- <a th:href="@{/portalnotice}" class="support-card support-card--notice">-->
|
|
||||||
<!-- <div class="card-icon">-->
|
|
||||||
<!-- <img th:src="@{/img/icon_notice.png}" alt="공지사항">-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="card-content">-->
|
|
||||||
<!-- <h3>공지사항</h3>-->
|
|
||||||
<!-- <p class="pc">DJBank API의 새로운 소식</p>-->
|
|
||||||
<!-- <p class="mobile">DJBank API의 <br/>새로운 소식</p>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </a>-->
|
|
||||||
|
|
||||||
<!-- <!– FAQ Card (25% width) –>-->
|
|
||||||
<!-- <a th:href="@{/faq_list}" class="support-card support-card--faq">-->
|
|
||||||
<!-- <div class="card-icon">-->
|
|
||||||
<!-- <img th:src="@{/img/icon_faq.png}" alt="FAQ">-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="card-content">-->
|
|
||||||
<!-- <h3>FAQ</h3>-->
|
|
||||||
<!-- <p>자주 묻는 질문</p>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </a>-->
|
|
||||||
|
|
||||||
<!-- <!– Q&A Card (25% width) –>-->
|
|
||||||
<!-- <a th:href="@{/inquiry}" class="support-card support-card--qna">-->
|
|
||||||
<!-- <div class="card-icon">-->
|
|
||||||
<!-- <img th:src="@{/img/icon_qna.png}" alt="Q&A">-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="card-content">-->
|
|
||||||
<!-- <h3>Q&A</h3>-->
|
|
||||||
<!-- <p>문의하기</p>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </a>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </section>-->
|
|
||||||
|
|
||||||
<section class="support-center">
|
<section class="support-center">
|
||||||
<div class="support-background"></div>
|
<div class="support-background"></div>
|
||||||
@@ -743,274 +588,276 @@
|
|||||||
<img class="ctaImg right" th:src="@{/img/avatar1.svg}" ali="아바타1">
|
<img class="ctaImg right" th:src="@{/img/avatar1.svg}" ali="아바타1">
|
||||||
<img class="ctaImg left" th:src="@{/img/avatar2.svg}" ali="아바타2">
|
<img class="ctaImg left" th:src="@{/img/avatar2.svg}" ali="아바타2">
|
||||||
</div>
|
</div>
|
||||||
<div class="cta-divider"></div>
|
|
||||||
</section>
|
</section>
|
||||||
</th:block>
|
</th:block>
|
||||||
</body>
|
</body>
|
||||||
<th:block layout:fragment="contentScript">
|
<th:block layout:fragment="contentScript">
|
||||||
<!-- 로그인 후 처리 스크립트 -->
|
<!-- 메인 페이지 전용 스크립트 모듈 추가 -->
|
||||||
<script th:src="@{/js/login-success-handler.js}"></script>
|
<script th:src="@{/js/main.js}"></script>
|
||||||
<script th:inline="javascript">
|
</th:block>
|
||||||
$(document).ready(function () {
|
|
||||||
LoginSuccessHandler.init({
|
</html>
|
||||||
successMsg: [[${ success }]],
|
<script th:inline="javascript">
|
||||||
emailVerificationRequired: [[${ session.emailVerificationRequired }]],
|
$(document).ready(function () {
|
||||||
dormantAccount: [[${ session.dormantAccount }]],
|
LoginSuccessHandler.init({
|
||||||
passwordExpired: [[${ session.passwordExpired }]],
|
successMsg: [[${ success }]],
|
||||||
pendingInvitation: [[${ session.pendingInvitation }]],
|
emailVerificationRequired: [[${ session.emailVerificationRequired }]],
|
||||||
pendingInvitationToken: [[${ session.pendingInvitationToken }]],
|
dormantAccount: [[${ session.dormantAccount }]],
|
||||||
pendingInvitationOrgName: [[${ session.pendingInvitationOrgName }]],
|
passwordExpired: [[${ session.passwordExpired }]],
|
||||||
sessionSuccessMsg: [[${ session.success }]],
|
pendingInvitation: [[${ session.pendingInvitation }]],
|
||||||
redirectUrl: [[${ session.redirectUrl }]]
|
pendingInvitationToken: [[${ session.pendingInvitationToken }]],
|
||||||
});
|
pendingInvitationOrgName: [[${ session.pendingInvitationOrgName }]],
|
||||||
|
sessionSuccessMsg: [[${ session.success }]],
|
||||||
|
redirectUrl: [[${ session.redirectUrl }]]
|
||||||
});
|
});
|
||||||
</script>
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
// ========================================
|
// ========================================
|
||||||
// Hero Carousel
|
// Hero Carousel
|
||||||
// ========================================
|
// ========================================
|
||||||
const heroCarousel = {
|
const heroCarousel = {
|
||||||
currentSlide: 0,
|
currentSlide: 0,
|
||||||
totalSlides: 3,
|
totalSlides: 3,
|
||||||
autoPlayInterval: null,
|
autoPlayInterval: null,
|
||||||
autoPlayDelay: 5000,
|
autoPlayDelay: 5000,
|
||||||
isPlaying: true,
|
isPlaying: true,
|
||||||
|
|
||||||
init: function () {
|
init: function () {
|
||||||
this.slides = document.querySelectorAll('.hero-slide');
|
this.slides = document.querySelectorAll('.hero-slide');
|
||||||
this.indicators = document.querySelectorAll('.hero-indicator');
|
this.indicators = document.querySelectorAll('.hero-indicator');
|
||||||
this.prevBtn = document.getElementById('heroPrevBtn');
|
this.prevBtn = document.getElementById('heroPrevBtn');
|
||||||
this.nextBtn = document.getElementById('heroNextBtn');
|
this.nextBtn = document.getElementById('heroNextBtn');
|
||||||
this.autoplayToggle = document.getElementById('heroAutoplayToggle');
|
this.autoplayToggle = document.getElementById('heroAutoplayToggle');
|
||||||
this.pauseIcon = this.autoplayToggle?.querySelector('.pause-icon');
|
this.pauseIcon = this.autoplayToggle?.querySelector('.pause-icon');
|
||||||
this.playIcon = this.autoplayToggle?.querySelector('.play-icon');
|
this.playIcon = this.autoplayToggle?.querySelector('.play-icon');
|
||||||
|
|
||||||
if (!this.slides.length) return;
|
if (!this.slides.length) return;
|
||||||
|
|
||||||
this.bindEvents();
|
this.bindEvents();
|
||||||
this.startAutoPlay();
|
this.startAutoPlay();
|
||||||
},
|
},
|
||||||
|
|
||||||
bindEvents: function () {
|
bindEvents: function () {
|
||||||
// Previous button
|
// Previous button
|
||||||
if (this.prevBtn) {
|
if (this.prevBtn) {
|
||||||
this.prevBtn.addEventListener('click', () => {
|
this.prevBtn.addEventListener('click', () => {
|
||||||
this.goToSlide(this.currentSlide - 1);
|
this.goToSlide(this.currentSlide - 1);
|
||||||
this.resetAutoPlay();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next button
|
|
||||||
if (this.nextBtn) {
|
|
||||||
this.nextBtn.addEventListener('click', () => {
|
|
||||||
this.goToSlide(this.currentSlide + 1);
|
|
||||||
this.resetAutoPlay();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indicators
|
|
||||||
this.indicators.forEach((indicator, index) => {
|
|
||||||
indicator.addEventListener('click', () => {
|
|
||||||
this.goToSlide(index);
|
|
||||||
this.resetAutoPlay();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Auto play toggle button
|
|
||||||
if (this.autoplayToggle) {
|
|
||||||
this.autoplayToggle.addEventListener('click', () => {
|
|
||||||
this.toggleAutoPlay();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pause on hover (only if playing)
|
|
||||||
const container = document.querySelector('.hero-carousel-container');
|
|
||||||
if (container) {
|
|
||||||
container.addEventListener('mouseenter', () => {
|
|
||||||
if (this.isPlaying) {
|
|
||||||
this.pauseAutoPlay();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
container.addEventListener('mouseleave', () => {
|
|
||||||
if (this.isPlaying) {
|
|
||||||
this.startAutoPlay();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Touch events for mobile
|
|
||||||
let touchStartX = 0;
|
|
||||||
let touchEndX = 0;
|
|
||||||
|
|
||||||
if (container) {
|
|
||||||
container.addEventListener('touchstart', (e) => {
|
|
||||||
touchStartX = e.changedTouches[0].screenX;
|
|
||||||
});
|
|
||||||
|
|
||||||
container.addEventListener('touchend', (e) => {
|
|
||||||
touchEndX = e.changedTouches[0].screenX;
|
|
||||||
this.handleSwipe(touchStartX, touchEndX);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
goToSlide: function (index) {
|
|
||||||
// Wrap around
|
|
||||||
if (index < 0) {
|
|
||||||
index = this.totalSlides - 1;
|
|
||||||
} else if (index >= this.totalSlides) {
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update slides
|
|
||||||
this.slides.forEach((slide, i) => {
|
|
||||||
slide.classList.toggle('active', i === index);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update indicators
|
|
||||||
this.indicators.forEach((indicator, i) => {
|
|
||||||
indicator.classList.toggle('active', i === index);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.currentSlide = index;
|
|
||||||
},
|
|
||||||
|
|
||||||
handleSwipe: function (startX, endX) {
|
|
||||||
const minSwipeDistance = 50;
|
|
||||||
const distance = startX - endX;
|
|
||||||
|
|
||||||
if (Math.abs(distance) > minSwipeDistance) {
|
|
||||||
if (distance > 0) {
|
|
||||||
// Swipe left - next slide
|
|
||||||
this.goToSlide(this.currentSlide + 1);
|
|
||||||
} else {
|
|
||||||
// Swipe right - previous slide
|
|
||||||
this.goToSlide(this.currentSlide - 1);
|
|
||||||
}
|
|
||||||
this.resetAutoPlay();
|
this.resetAutoPlay();
|
||||||
}
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
startAutoPlay: function () {
|
// Next button
|
||||||
this.pauseAutoPlay();
|
if (this.nextBtn) {
|
||||||
this.autoPlayInterval = setInterval(() => {
|
this.nextBtn.addEventListener('click', () => {
|
||||||
this.goToSlide(this.currentSlide + 1);
|
this.goToSlide(this.currentSlide + 1);
|
||||||
}, this.autoPlayDelay);
|
this.resetAutoPlay();
|
||||||
},
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pauseAutoPlay: function () {
|
// Indicators
|
||||||
if (this.autoPlayInterval) {
|
this.indicators.forEach((indicator, index) => {
|
||||||
clearInterval(this.autoPlayInterval);
|
indicator.addEventListener('click', () => {
|
||||||
this.autoPlayInterval = null;
|
this.goToSlide(index);
|
||||||
}
|
this.resetAutoPlay();
|
||||||
},
|
});
|
||||||
|
});
|
||||||
|
|
||||||
resetAutoPlay: function () {
|
// Auto play toggle button
|
||||||
if (this.isPlaying) {
|
if (this.autoplayToggle) {
|
||||||
this.pauseAutoPlay();
|
this.autoplayToggle.addEventListener('click', () => {
|
||||||
this.startAutoPlay();
|
this.toggleAutoPlay();
|
||||||
}
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
toggleAutoPlay: function () {
|
// Pause on hover (only if playing)
|
||||||
this.isPlaying = !this.isPlaying;
|
const container = document.querySelector('.hero-carousel-container');
|
||||||
|
if (container) {
|
||||||
if (this.isPlaying) {
|
container.addEventListener('mouseenter', () => {
|
||||||
// Start auto play
|
if (this.isPlaying) {
|
||||||
this.startAutoPlay();
|
this.pauseAutoPlay();
|
||||||
// Update icons
|
|
||||||
if (this.pauseIcon) this.pauseIcon.classList.add('active');
|
|
||||||
if (this.playIcon) this.playIcon.classList.remove('active');
|
|
||||||
// Update aria-label
|
|
||||||
if (this.autoplayToggle) {
|
|
||||||
this.autoplayToggle.setAttribute('aria-label', '자동 재생 일시정지');
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
container.addEventListener('mouseleave', () => {
|
||||||
|
if (this.isPlaying) {
|
||||||
|
this.startAutoPlay();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Touch events for mobile
|
||||||
|
let touchStartX = 0;
|
||||||
|
let touchEndX = 0;
|
||||||
|
|
||||||
|
if (container) {
|
||||||
|
container.addEventListener('touchstart', (e) => {
|
||||||
|
touchStartX = e.changedTouches[0].screenX;
|
||||||
|
});
|
||||||
|
|
||||||
|
container.addEventListener('touchend', (e) => {
|
||||||
|
touchEndX = e.changedTouches[0].screenX;
|
||||||
|
this.handleSwipe(touchStartX, touchEndX);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
goToSlide: function (index) {
|
||||||
|
// Wrap around
|
||||||
|
if (index < 0) {
|
||||||
|
index = this.totalSlides - 1;
|
||||||
|
} else if (index >= this.totalSlides) {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update slides
|
||||||
|
this.slides.forEach((slide, i) => {
|
||||||
|
slide.classList.toggle('active', i === index);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update indicators
|
||||||
|
this.indicators.forEach((indicator, i) => {
|
||||||
|
indicator.classList.toggle('active', i === index);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.currentSlide = index;
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSwipe: function (startX, endX) {
|
||||||
|
const minSwipeDistance = 50;
|
||||||
|
const distance = startX - endX;
|
||||||
|
|
||||||
|
if (Math.abs(distance) > minSwipeDistance) {
|
||||||
|
if (distance > 0) {
|
||||||
|
// Swipe left - next slide
|
||||||
|
this.goToSlide(this.currentSlide + 1);
|
||||||
} else {
|
} else {
|
||||||
// Stop auto play
|
// Swipe right - previous slide
|
||||||
this.pauseAutoPlay();
|
this.goToSlide(this.currentSlide - 1);
|
||||||
// Update icons
|
}
|
||||||
if (this.pauseIcon) this.pauseIcon.classList.remove('active');
|
this.resetAutoPlay();
|
||||||
if (this.playIcon) this.playIcon.classList.add('active');
|
}
|
||||||
// Update aria-label
|
},
|
||||||
if (this.autoplayToggle) {
|
|
||||||
this.autoplayToggle.setAttribute('aria-label', '자동 재생 시작');
|
startAutoPlay: function () {
|
||||||
}
|
this.pauseAutoPlay();
|
||||||
|
this.autoPlayInterval = setInterval(() => {
|
||||||
|
this.goToSlide(this.currentSlide + 1);
|
||||||
|
}, this.autoPlayDelay);
|
||||||
|
},
|
||||||
|
|
||||||
|
pauseAutoPlay: function () {
|
||||||
|
if (this.autoPlayInterval) {
|
||||||
|
clearInterval(this.autoPlayInterval);
|
||||||
|
this.autoPlayInterval = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
resetAutoPlay: function () {
|
||||||
|
if (this.isPlaying) {
|
||||||
|
this.pauseAutoPlay();
|
||||||
|
this.startAutoPlay();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleAutoPlay: function () {
|
||||||
|
this.isPlaying = !this.isPlaying;
|
||||||
|
|
||||||
|
if (this.isPlaying) {
|
||||||
|
// Start auto play
|
||||||
|
this.startAutoPlay();
|
||||||
|
// Update icons
|
||||||
|
if (this.pauseIcon) this.pauseIcon.classList.add('active');
|
||||||
|
if (this.playIcon) this.playIcon.classList.remove('active');
|
||||||
|
// Update aria-label
|
||||||
|
if (this.autoplayToggle) {
|
||||||
|
this.autoplayToggle.setAttribute('aria-label', '자동 재생 일시정지');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Stop auto play
|
||||||
|
this.pauseAutoPlay();
|
||||||
|
// Update icons
|
||||||
|
if (this.pauseIcon) this.pauseIcon.classList.remove('active');
|
||||||
|
if (this.playIcon) this.playIcon.classList.add('active');
|
||||||
|
// Update aria-label
|
||||||
|
if (this.autoplayToggle) {
|
||||||
|
this.autoplayToggle.setAttribute('aria-label', '자동 재생 시작');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize hero carousel
|
|
||||||
heroCarousel.init();
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// API 검색 기능
|
|
||||||
// ========================================
|
|
||||||
const searchInput = document.getElementById('apiSearchInput');
|
|
||||||
const searchForm = document.querySelector('.search-form');
|
|
||||||
const hashtags = document.querySelectorAll('.hashtag-link');
|
|
||||||
|
|
||||||
// 해시태그 클릭 이벤트
|
|
||||||
hashtags.forEach(tag => {
|
|
||||||
tag.addEventListener('click', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const searchTerm = this.getAttribute('data-search');
|
|
||||||
if (searchInput) {
|
|
||||||
searchInput.value = searchTerm;
|
|
||||||
}
|
|
||||||
// 폼 제출
|
|
||||||
if (searchForm) {
|
|
||||||
searchForm.submit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// 숫자 카운트업 애니메이션
|
|
||||||
// ========================================
|
|
||||||
const observerOptions = {
|
|
||||||
threshold: 0.5,
|
|
||||||
rootMargin: '0px 0px -100px 0px'
|
|
||||||
};
|
|
||||||
|
|
||||||
const animateNumbers = (entries, observer) => {
|
|
||||||
entries.forEach(entry => {
|
|
||||||
if (entry.isIntersecting) {
|
|
||||||
const numbers = entry.target.querySelectorAll('.stat-number');
|
|
||||||
|
|
||||||
numbers.forEach(number => {
|
|
||||||
const target = parseInt(number.getAttribute('data-target'));
|
|
||||||
const duration = 2000; // 2초
|
|
||||||
const increment = target / (duration / 16);
|
|
||||||
let current = 0;
|
|
||||||
|
|
||||||
const updateNumber = () => {
|
|
||||||
current += increment;
|
|
||||||
if (current < target) {
|
|
||||||
number.textContent = Math.floor(current).toLocaleString('ko-KR');
|
|
||||||
requestAnimationFrame(updateNumber);
|
|
||||||
} else {
|
|
||||||
number.textContent = target.toLocaleString('ko-KR');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
updateNumber();
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.unobserve(entry.target);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const observer = new IntersectionObserver(animateNumbers, observerOptions);
|
|
||||||
const statsSection = document.querySelector('.api-stats-section');
|
|
||||||
|
|
||||||
if (statsSection) {
|
|
||||||
observer.observe(statsSection);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize hero carousel
|
||||||
|
heroCarousel.init();
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// API 검색 기능
|
||||||
|
// ========================================
|
||||||
|
const searchInput = document.getElementById('apiSearchInput');
|
||||||
|
const searchForm = document.querySelector('.search-form');
|
||||||
|
const hashtags = document.querySelectorAll('.hashtag-link');
|
||||||
|
|
||||||
|
// 해시태그 클릭 이벤트
|
||||||
|
hashtags.forEach(tag => {
|
||||||
|
tag.addEventListener('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const searchTerm = this.getAttribute('data-search');
|
||||||
|
if (searchInput) {
|
||||||
|
searchInput.value = searchTerm;
|
||||||
|
}
|
||||||
|
// 폼 제출
|
||||||
|
if (searchForm) {
|
||||||
|
searchForm.submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
|
// ========================================
|
||||||
|
// 숫자 카운트업 애니메이션
|
||||||
|
// ========================================
|
||||||
|
const observerOptions = {
|
||||||
|
threshold: 0.5,
|
||||||
|
rootMargin: '0px 0px -100px 0px'
|
||||||
|
};
|
||||||
|
|
||||||
|
const animateNumbers = (entries, observer) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
const numbers = entry.target.querySelectorAll('.stat-number');
|
||||||
|
|
||||||
|
numbers.forEach(number => {
|
||||||
|
const target = parseInt(number.getAttribute('data-target'));
|
||||||
|
const duration = 2000; // 2초
|
||||||
|
const increment = target / (duration / 16);
|
||||||
|
let current = 0;
|
||||||
|
|
||||||
|
const updateNumber = () => {
|
||||||
|
current += increment;
|
||||||
|
if (current < target) {
|
||||||
|
number.textContent = Math.floor(current).toLocaleString('ko-KR');
|
||||||
|
requestAnimationFrame(updateNumber);
|
||||||
|
} else {
|
||||||
|
number.textContent = target.toLocaleString('ko-KR');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
updateNumber();
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.unobserve(entry.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(animateNumbers, observerOptions);
|
||||||
|
const statsSection = document.querySelector('.api-stats-section');
|
||||||
|
|
||||||
|
if (statsSection) {
|
||||||
|
observer.observe(statsSection);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user