첫 커밋
This commit is contained in:
359
src/shared/ui/assets/js/motion.js
Normal file
359
src/shared/ui/assets/js/motion.js
Normal file
@@ -0,0 +1,359 @@
|
||||
// mobile 100vh err issue 대응
|
||||
|
||||
const setVh = () => {document.documentElement.style.setProperty('--vh', `${window.innerHeight}px`)};
|
||||
window.addEventListener('resize', setVh);
|
||||
setVh();
|
||||
|
||||
// touchstart 이벤트 (jQuery 제거)
|
||||
document.addEventListener('touchstart', function(){ });
|
||||
|
||||
// 탭 전환 기능
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const tabButtons = document.querySelectorAll('.tab-button');
|
||||
const tabPanes = document.querySelectorAll('.tab-pane');
|
||||
|
||||
tabButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const targetTab = this.getAttribute('data-tab');
|
||||
|
||||
// 더보기 버튼(tab5)은 탭 전환하지 않음
|
||||
if (targetTab === 'tab5') {
|
||||
return;
|
||||
}
|
||||
|
||||
// 모든 탭 버튼에서 active 클래스 제거
|
||||
tabButtons.forEach(btn => btn.classList.remove('active'));
|
||||
// 모든 탭 패널에서 active 클래스 제거
|
||||
tabPanes.forEach(pane => pane.classList.remove('active'));
|
||||
|
||||
// 클릭된 버튼에 active 클래스 추가
|
||||
this.classList.add('active');
|
||||
// 해당 탭 패널에 active 클래스 추가
|
||||
document.getElementById(targetTab).classList.add('active');
|
||||
|
||||
// 아이콘 변경
|
||||
updateTabIcons();
|
||||
});
|
||||
});
|
||||
|
||||
// 헤더 버튼 기능
|
||||
const profileBtn = document.getElementById('profileBtn');
|
||||
|
||||
// 프로필 버튼 클릭 이벤트
|
||||
if (profileBtn) {
|
||||
profileBtn.addEventListener('click', function() {
|
||||
// 프로필 탭으로 이동
|
||||
const profileTab = document.querySelector('[data-tab="tab5"]');
|
||||
if (profileTab) {
|
||||
profileTab.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 탭 아이콘 업데이트 함수
|
||||
function updateTabIcons() {
|
||||
tabButtons.forEach(button => {
|
||||
const iconElement = button.querySelector('.tab-icon-img');
|
||||
const isActive = button.classList.contains('active');
|
||||
|
||||
if (isActive) {
|
||||
const activeIcon = button.getAttribute('data-active-icon');
|
||||
iconElement.src = activeIcon;
|
||||
} else {
|
||||
const inactiveIcon = button.getAttribute('data-inactive-icon');
|
||||
iconElement.src = inactiveIcon;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 초기 아이콘 설정
|
||||
updateTabIcons();
|
||||
|
||||
// heading-select 자동 너비 조정
|
||||
const headingSelect = document.querySelector('.heading-select');
|
||||
|
||||
function adjustSelectWidth() {
|
||||
if (headingSelect) {
|
||||
// 임시 span 요소 생성하여 텍스트 길이 측정
|
||||
const tempSpan = document.createElement('span');
|
||||
tempSpan.style.visibility = 'hidden';
|
||||
tempSpan.style.position = 'absolute';
|
||||
tempSpan.style.whiteSpace = 'nowrap';
|
||||
tempSpan.style.fontSize = window.getComputedStyle(headingSelect).fontSize;
|
||||
tempSpan.style.fontFamily = window.getComputedStyle(headingSelect).fontFamily;
|
||||
tempSpan.style.fontWeight = window.getComputedStyle(headingSelect).fontWeight;
|
||||
|
||||
// 선택된 옵션의 텍스트 가져오기
|
||||
const selectedOption = headingSelect.options[headingSelect.selectedIndex];
|
||||
tempSpan.textContent = selectedOption ? selectedOption.text : '';
|
||||
|
||||
// body에 임시 추가하여 측정
|
||||
document.body.appendChild(tempSpan);
|
||||
|
||||
// 텍스트 너비 측정 (패딩과 화살표 아이콘 공간 추가)
|
||||
const textWidth = tempSpan.offsetWidth;
|
||||
const padding = 40; // 좌우 패딩과 화살표 아이콘 공간
|
||||
const newWidth = textWidth + padding;
|
||||
|
||||
// select 너비 설정
|
||||
headingSelect.style.width = newWidth + 'px';
|
||||
|
||||
// 임시 요소 제거
|
||||
document.body.removeChild(tempSpan);
|
||||
}
|
||||
}
|
||||
|
||||
// 초기 너비 조정
|
||||
adjustSelectWidth();
|
||||
|
||||
// select 변경 시 너비 재조정
|
||||
if (headingSelect) {
|
||||
headingSelect.addEventListener('change', adjustSelectWidth);
|
||||
}
|
||||
|
||||
// 스와이퍼 아이템 클릭 이벤트
|
||||
const swiperItems = document.querySelectorAll('.swiper-item');
|
||||
swiperItems.forEach((item, index) => {
|
||||
item.addEventListener('click', () => {
|
||||
console.log(`스와이퍼 아이템 ${index + 1} 클릭됨`);
|
||||
|
||||
// 각 아이템별 기능
|
||||
switch(index) {
|
||||
case 0: // 코인
|
||||
console.log('코인 기능 실행');
|
||||
break;
|
||||
case 1: // 차트
|
||||
console.log('차트 기능 실행');
|
||||
break;
|
||||
case 2: // 캘린더
|
||||
console.log('캘린더 기능 실행');
|
||||
break;
|
||||
case 3: // 추가
|
||||
console.log('추가 기능 실행');
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// day-tab 전환 기능
|
||||
const dayTabBtns = document.querySelectorAll('.day-tab-btn');
|
||||
const conBoxes = document.querySelectorAll('.con-box');
|
||||
|
||||
dayTabBtns.forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
const target = this.getAttribute('data-target');
|
||||
|
||||
// 모든 탭 버튼에서 active 클래스 제거
|
||||
dayTabBtns.forEach(b => b.classList.remove('active'));
|
||||
// 모든 컨텐츠 박스에서 active 클래스 제거
|
||||
conBoxes.forEach(box => box.classList.remove('active'));
|
||||
|
||||
// 클릭된 버튼에 active 클래스 추가
|
||||
this.classList.add('active');
|
||||
// 해당 컨텐츠 박스에 active 클래스 추가
|
||||
document.querySelector(`.con-box.${target}`).classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
// 배너 슬라이드 기능
|
||||
const bannerSlides = document.querySelectorAll('.banner-slide');
|
||||
const bannerDots = document.querySelectorAll('.banner-dot');
|
||||
const bannerWrapper = document.querySelector('.banner-wrapper');
|
||||
let currentSlide = 0;
|
||||
let slideInterval;
|
||||
let isDragging = false;
|
||||
let startX = 0;
|
||||
let currentX = 0;
|
||||
let slideWidth = 0;
|
||||
|
||||
function showSlide(index) {
|
||||
// 모든 슬라이드에서 active와 prev 클래스 제거
|
||||
bannerSlides.forEach(slide => {
|
||||
slide.classList.remove('active', 'prev');
|
||||
});
|
||||
|
||||
// 모든 페이지네이션 점에서 active 클래스 제거
|
||||
bannerDots.forEach(dot => dot.classList.remove('active'));
|
||||
|
||||
// 현재 슬라이드 활성화
|
||||
bannerSlides[index].classList.add('active');
|
||||
bannerDots[index].classList.add('active');
|
||||
|
||||
// 이전 슬라이드에 prev 클래스 추가 (x축 슬라이드 효과)
|
||||
const prevIndex = (index - 1 + bannerSlides.length) % bannerSlides.length;
|
||||
bannerSlides[prevIndex].classList.add('prev');
|
||||
|
||||
currentSlide = index;
|
||||
}
|
||||
|
||||
function nextSlide() {
|
||||
const nextIndex = (currentSlide + 1) % bannerSlides.length;
|
||||
showSlide(nextIndex);
|
||||
}
|
||||
|
||||
function prevSlide() {
|
||||
const prevIndex = (currentSlide - 1 + bannerSlides.length) % bannerSlides.length;
|
||||
showSlide(prevIndex);
|
||||
}
|
||||
|
||||
// 페이지네이션 클릭 이벤트
|
||||
bannerDots.forEach((dot, index) => {
|
||||
dot.addEventListener('click', () => {
|
||||
showSlide(index);
|
||||
resetAutoSlide();
|
||||
});
|
||||
});
|
||||
|
||||
// 터치/마우스 드래그 기능
|
||||
if (bannerWrapper) {
|
||||
// 마우스 이벤트
|
||||
bannerWrapper.addEventListener('mousedown', (e) => {
|
||||
isDragging = true;
|
||||
startX = e.pageX;
|
||||
currentX = startX;
|
||||
bannerWrapper.style.cursor = 'grabbing';
|
||||
clearInterval(slideInterval);
|
||||
});
|
||||
|
||||
bannerWrapper.addEventListener('mousemove', (e) => {
|
||||
if (!isDragging) return;
|
||||
e.preventDefault();
|
||||
currentX = e.pageX;
|
||||
});
|
||||
|
||||
bannerWrapper.addEventListener('mouseup', () => {
|
||||
if (isDragging) {
|
||||
handleDragEnd();
|
||||
}
|
||||
});
|
||||
|
||||
bannerWrapper.addEventListener('mouseleave', () => {
|
||||
if (isDragging) {
|
||||
handleDragEnd();
|
||||
}
|
||||
});
|
||||
|
||||
// 터치 이벤트
|
||||
bannerWrapper.addEventListener('touchstart', (e) => {
|
||||
isDragging = true;
|
||||
startX = e.touches[0].pageX;
|
||||
currentX = startX;
|
||||
clearInterval(slideInterval);
|
||||
});
|
||||
|
||||
bannerWrapper.addEventListener('touchmove', (e) => {
|
||||
if (!isDragging) return;
|
||||
e.preventDefault();
|
||||
currentX = e.touches[0].pageX;
|
||||
});
|
||||
|
||||
bannerWrapper.addEventListener('touchend', () => {
|
||||
if (isDragging) {
|
||||
handleDragEnd();
|
||||
}
|
||||
});
|
||||
|
||||
function handleDragEnd() {
|
||||
isDragging = false;
|
||||
bannerWrapper.style.cursor = 'grab';
|
||||
|
||||
const dragDistance = startX - currentX;
|
||||
const threshold = 50; // 드래그 임계값
|
||||
|
||||
if (Math.abs(dragDistance) > threshold) {
|
||||
if (dragDistance > 0) {
|
||||
// 왼쪽으로 드래그 - 다음 슬라이드
|
||||
nextSlide();
|
||||
} else {
|
||||
// 오른쪽으로 드래그 - 이전 슬라이드
|
||||
prevSlide();
|
||||
}
|
||||
}
|
||||
|
||||
resetAutoSlide();
|
||||
}
|
||||
}
|
||||
|
||||
// 자동 슬라이드 시작
|
||||
function startAutoSlide() {
|
||||
slideInterval = setInterval(nextSlide, 3000); // 3초마다 슬라이드
|
||||
}
|
||||
|
||||
// 자동 슬라이드 리셋
|
||||
function resetAutoSlide() {
|
||||
clearInterval(slideInterval);
|
||||
startAutoSlide();
|
||||
}
|
||||
|
||||
// 자동 슬라이드 시작
|
||||
if (bannerSlides.length > 0) {
|
||||
startAutoSlide();
|
||||
}
|
||||
|
||||
// 전체메뉴 모달 기능
|
||||
const fullMenuModal = document.getElementById('fullMenuModal');
|
||||
const closeFullMenu = document.getElementById('closeFullMenu');
|
||||
|
||||
// 더보기 탭 버튼 클릭 시 전체메뉴 모달 열기
|
||||
const moreTabButton = document.querySelector('[data-tab="tab5"]');
|
||||
if (moreTabButton) {
|
||||
moreTabButton.addEventListener('click', function(e) {
|
||||
e.preventDefault(); // 기본 동작 방지
|
||||
e.stopPropagation(); // 이벤트 버블링 방지
|
||||
|
||||
if (fullMenuModal) {
|
||||
fullMenuModal.style.display = 'block';
|
||||
document.body.style.overflow = 'hidden'; // 배경 스크롤 방지
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 닫기 버튼 클릭 시 모달 닫기
|
||||
if (closeFullMenu) {
|
||||
closeFullMenu.addEventListener('click', function() {
|
||||
if (fullMenuModal) {
|
||||
fullMenuModal.style.display = 'none';
|
||||
document.body.style.overflow = ''; // 배경 스크롤 복원
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 모달 외부 클릭 시 닫기
|
||||
if (fullMenuModal) {
|
||||
fullMenuModal.addEventListener('click', function(e) {
|
||||
if (e.target === fullMenuModal) {
|
||||
fullMenuModal.style.display = 'none';
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 인기 키워드 클릭 이벤트
|
||||
const keywordTags = document.querySelectorAll('.keyword-tag');
|
||||
keywordTags.forEach(tag => {
|
||||
tag.addEventListener('click', function() {
|
||||
// 모든 키워드 태그에서 active 클래스 제거
|
||||
keywordTags.forEach(t => t.classList.remove('active'));
|
||||
// 클릭된 태그에 active 클래스 추가
|
||||
this.classList.add('active');
|
||||
});
|
||||
});
|
||||
|
||||
// 메뉴 아이템 클릭 이벤트
|
||||
const menuItems = document.querySelectorAll('.category-items li');
|
||||
menuItems.forEach(item => {
|
||||
item.addEventListener('click', function() {
|
||||
console.log('메뉴 클릭:', this.textContent);
|
||||
// 여기에 각 메뉴별 기능을 추가할 수 있습니다
|
||||
});
|
||||
});
|
||||
|
||||
// 상단 네비게이션 아이템 클릭 이벤트
|
||||
const topNavItems = document.querySelectorAll('.top-nav-item');
|
||||
topNavItems.forEach(item => {
|
||||
item.addEventListener('click', function() {
|
||||
console.log('상단 네비게이션 클릭:', this.querySelector('span').textContent);
|
||||
// 여기에 각 네비게이션별 기능을 추가할 수 있습니다
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user