슬라이드를 넣고 싶을때, 주로 플러그인을 활용하지만
종종, 간단한 슬라이드가 필요할때가 있습니다.
그래서 모바일에서 터치 슬라이드로 활용할 수 있는 슬라이드를 만들고자,
클로드 ai를 활용해서 슬라이드를 제작해 봤습니다.
코드 생성은 클로드 https://claude.ai/ 를 활용했습니다.
클로드 ai 요청 명령어
" html 과 css 만으로 모바일에서 좌우로 스와이프 되는 기능이 있는 슬라이드를 만드려고해. 오른쪽이나 왼쪽으로 스와이프 하면 다음이나 이전 페이지로 넘어가는거야. 각 페이지에는 정중안에는 h3의 텍스트가 위치해 있어. 페이지는 무한정으로 생산 가능하게"
1. html
<div class="slider-container">
<div class="slider-wrapper">
<div class="slide">
<h3>첫번째 슬라이드</h3>
</div>
<div class="slide">
<h3>두번째 슬라이드</h3>
</div>
<div class="slide">
<h3>세번째 슬라이드</h3>
</div>
<div class="slide">
<h3>네번째 슬라이드</h3>
</div>
<!-- 여기에 더 많은 슬라이드를 추가할 수 있습니다 -->
</div>
<div class="pagination"></div>
<button class="nav-button prev">←</button>
<button class="nav-button next">→</button>
</div>
2. CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
overflow: hidden;
touch-action: pan-y;
}
.slider-container {
width: 100%;
height: 100vh;
overflow: hidden;
position: relative;
}
.slider-wrapper {
display: flex;
height: 100%;
transition: transform 0.3s ease-out;
}
.slide {
min-width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
user-select: none;
}
.slide:nth-child(odd) {
background-color: #f5f5f5;
}
.slide:nth-child(even) {
background-color: #e0e0e0;
}
h3 {
font-size: 24px;
text-align: center;
padding: 20px;
}
.pagination {
position: absolute;
bottom: 20px;
left: 0;
right: 0;
display: flex;
justify-content: center;
gap: 10px;
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #bbb;
cursor: pointer;
}
.dot.active {
background-color: #333;
}
.nav-button {
position: absolute;
top: 50%;
transform: translateY(-50%);
background-color: rgba(255, 255, 255, 0.7);
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
font-size: 18px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
.prev {
left: 10px;
}
.next {
right: 10px;
}
3. Javascript
document.addEventListener('DOMContentLoaded', function() {
const sliderWrapper = document.querySelector('.slider-wrapper');
const slides = document.querySelectorAll('.slide');
const pagination = document.querySelector('.pagination');
const prevButton = document.querySelector('.prev');
const nextButton = document.querySelector('.next');
let currentIndex = 0;
let startX;
let isDragging = false;
let slideWidth = slides[0].offsetWidth;
let transformValue = 0;
// 페이지네이션 점 생성
slides.forEach((_, index) => {
const dot = document.createElement('div');
dot.classList.add('dot');
if (index === 0) dot.classList.add('active');
dot.addEventListener('click', () => goToSlide(index));
pagination.appendChild(dot);
});
// 초기 설정
updateSlider();
// 창 크기가 변경될 때 슬라이드 너비 업데이트
window.addEventListener('resize', () => {
slideWidth = slides[0].offsetWidth;
updateSlider();
});
// 터치 이벤트
sliderWrapper.addEventListener('touchstart', handleTouchStart, false);
sliderWrapper.addEventListener('touchmove', handleTouchMove, false);
sliderWrapper.addEventListener('touchend', handleTouchEnd, false);
// 마우스 이벤트 (데스크탑 지원)
sliderWrapper.addEventListener('mousedown', handleMouseDown, false);
sliderWrapper.addEventListener('mousemove', handleMouseMove, false);
sliderWrapper.addEventListener('mouseup', handleMouseUp, false);
sliderWrapper.addEventListener('mouseleave', handleMouseUp, false);
// 버튼 이벤트
prevButton.addEventListener('click', goToPrev);
nextButton.addEventListener('click', goToNext);
function handleTouchStart(e) {
startX = e.touches[0].clientX;
isDragging = true;
sliderWrapper.style.transition = 'none';
}
function handleTouchMove(e) {
if (!isDragging) return;
const currentX = e.touches[0].clientX;
const diff = currentX - startX;
transformValue = -currentIndex * slideWidth + diff;
sliderWrapper.style.transform = `translateX(${transformValue}px)`;
}
function handleTouchEnd(e) {
if (!isDragging) return;
isDragging = false;
sliderWrapper.style.transition = 'transform 0.3s ease-out';
const currentX = e.changedTouches[0].clientX;
const diff = currentX - startX;
if (diff > 50) {
goToPrev();
} else if (diff < -50) {
goToNext();
} else {
updateSlider();
}
}
function handleMouseDown(e) {
e.preventDefault();
startX = e.clientX;
isDragging = true;
sliderWrapper.style.transition = 'none';
}
function handleMouseMove(e) {
if (!isDragging) return;
const currentX = e.clientX;
const diff = currentX - startX;
transformValue = -currentIndex * slideWidth + diff;
sliderWrapper.style.transform = `translateX(${transformValue}px)`;
}
function handleMouseUp(e) {
if (!isDragging) return;
isDragging = false;
sliderWrapper.style.transition = 'transform 0.3s ease-out';
if (e.type === 'mouseleave') {
updateSlider();
return;
}
const currentX = e.clientX;
const diff = currentX - startX;
if (diff > 50) {
goToPrev();
} else if (diff < -50) {
goToNext();
} else {
updateSlider();
}
}
function goToPrev() {
currentIndex = (currentIndex - 1 + slides.length) % slides.length;
updateSlider();
}
function goToNext() {
currentIndex = (currentIndex + 1) % slides.length;
updateSlider();
}
function goToSlide(index) {
currentIndex = index;
updateSlider();
}
function updateSlider() {
sliderWrapper.style.transform = `translateX(${-currentIndex * slideWidth}px)`;
// 페이지네이션 업데이트
document.querySelectorAll('.dot').forEach((dot, index) => {
if (index === currentIndex) {
dot.classList.add('active');
} else {
dot.classList.remove('active');
}
});
}
// 무한 슬라이드를 위한 복제 슬라이드 추가 함수
function addCloneSlides() {
// 첫 번째 슬라이드와 마지막 슬라이드를 복제해서 앞과 뒤에 추가
const firstSlide = slides[0].cloneNode(true);
const lastSlide = slides[slides.length - 1].cloneNode(true);
sliderWrapper.appendChild(firstSlide);
sliderWrapper.insertBefore(lastSlide, slides[0]);
// 복제된 슬라이드를 고려하여 인덱스 조정
currentIndex = 1;
updateSlider();
}
});
4. 최종 파일 다운로드
결과 보기
728x90
반응형
'퍼블리싱' 카테고리의 다른 글
리액트 네이티브, <br> 태그 줄바꿈 하기 (1) | 2025.02.04 |
---|---|
[웹폰트 사용방법] 웹에 최적화된포맷 - woff2 (0) | 2024.08.29 |
[CSS] 변수를 음수로 변환하는 방법 (0) | 2024.08.02 |
[Javascript, css] 스크롤 내리면 카운팅 시작 되는 소스 (0) | 2024.06.25 |
[CSS]마우스 호버시 아이콘 모양 변경(사이드바 보기/감추기역할) (0) | 2024.06.19 |
댓글