티스토리 뷰

WEB/JavaScript

[JavaScript]슬라이드 이미지

silverline79 2026. 1. 3. 16:18
슬라이드 자동 재생 코드 슬라이드 자동 재생 코드_재생정지버튼추가
슬라이드 자동 재생 코드_재생정지버튼추가_페이지 슬라이드 자동 재생 코드 _재생정지버튼추가_페이지_인디케이터
슬라이드 자동 재생 코드 _재생정지버튼추가_페이지_인디케이터 반응형

 

슬라이드 자동 재생 코드.html

슬라이드 자동 재생 코드.html
0.00MB

 

슬라이드 자동 재생 코드_재생정지버튼추가.html

슬라이드 자동 재생 코드_재생정지버튼추가.html
0.00MB

 

슬라이드 자동 재생 코드_재생정지버튼추가_페이지.html

슬라이드 자동 재생 코드_재생정지버튼추가_페이지.html
0.00MB

 

슬라이드 자동 재생 코드_재생정지버튼추가_페이지_인디케이터.html

슬라이드 자동 재생 코드_재생정지버튼추가_페이지_인디케이터.html
0.01MB

 

슬라이드 자동 재생 코드_재생정지버튼추가_페이지_인디케이터_반응형.html

슬라이드 자동 재생 코드_재생정지버튼추가_페이지_인디케이터_반응형.html
0.01MB

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>반응형 인디케이터 슬라이더</title>
    <style>
        /* 1. 반응형 레이아웃 설정 */
        .slider-container { 
            width: 90%;          /* 모바일에서도 여백이 있도록 비율 설정 */
            max-width: 800px;    /* 최대 너비 제한 */
            aspect-ratio: 16 / 9; /* 이미지 비율 고정 (반응형의 핵심) */
            margin: 50px auto;
            overflow: hidden; 
            position: relative; 
            border-radius: 12px;
            background: #eee;
        }
        
        .slide-track { 
            display: flex; 
            transition: transform 0.5s ease-in-out; 
            height: 100%;
        }
        
        .slide-track img { 
            flex: 0 0 100%;      /* 부모 너비의 100%를 꽉 채움 */
            width: 100%; 
            height: 100%; 
            object-fit: cover; 
        }
        
        /* 버튼 및 컨트롤러는 이전과 동일하되, 모바일 배려 */
        .nav-btn {
            position: absolute; top: 50%; transform: translateY(-50%);
            background: rgba(0,0,0,0.3); color: #fff; border: none;
            padding: 10px; cursor: pointer; border-radius: 50%; width: 40px; height: 40px; z-index: 10;
        }
        .prev-btn { left: 10px; }
        .next-btn { right: 10px; }

        .control-panel {
            position: absolute; bottom: 15px; left: 50%; transform: translateX(-50%);
            display: flex; align-items: center; gap: 10px;
            background: rgba(0,0,0,0.5); padding: 8px 15px; border-radius: 20px;
            color: #fff; font-size: 12px; z-index: 10; white-space: nowrap;
        }

        .indicator-group { display: flex; gap: 8px; }
        .dot {
            width: 8px; height: 8px; background: rgba(255,255,255,0.4);
            border-radius: 50%; cursor: pointer; border: none; padding: 0;
        }
        .dot.active { background: #fff; transform: scale(1.2); }

        .play-pause-btn {
            background: none; border: none; color: #fff; cursor: pointer; 
            font-weight: bold; border-left: 1px solid rgba(255,255,255,0.3);
            padding-left: 10px; margin-left: 5px;
        }

        /* 모바일용 스타일 조정 */
        @media (max-width: 480px) {
            .nav-btn { width: 30px; height: 30px; padding: 5px; font-size: 12px; }
            .control-panel { padding: 5px 10px; font-size: 10px; }
        }
    </style>
</head>
<body>

    <div class="slider-container" id="sliderMain">
        <div class="slide-track" id="track">
            <img src="https://picsum.photos/id/10/800/450" alt="1">
            <img src="https://picsum.photos/id/20/800/450" alt="2">
            <img src="https://picsum.photos/id/30/800/450" alt="3">
        </div>
        
        <button class="nav-btn prev-btn" id="prevBtn">❮</button>
        <button class="nav-btn next-btn" id="nextBtn">❯</button>

        <div class="control-panel">
            <div class="indicator-group" id="indicatorGroup">
                <button class="dot active"></button>
                <button class="dot"></button>
                <button class="dot"></button>
            </div>
            <div class="page-num" id="pageNum">1 / 3</div>
            <button class="play-pause-btn" id="playPauseBtn">PAUSE</button>
        </div>
    </div>

    <script>
        const sliderMain = document.getElementById('sliderMain');
        const track = document.getElementById('track');
        const nextBtn = document.getElementById('nextBtn');
        const prevBtn = document.getElementById('prevBtn');
        const playPauseBtn = document.getElementById('playPauseBtn');
        const pageNum = document.getElementById('pageNum');
        const dots = document.querySelectorAll('.dot');
        
        let index = 0;
        const totalSlides = dots.length;
        let slideTimer;
        let isPlaying = true;

        // [반응형 핵심] 현재 슬라이더의 너비를 계산하는 함수
        function updateUI() {
            const sliderWidth = sliderMain.clientWidth; // 고정값이 아닌 현재 너비를 가져옴
            track.style.transform = `translateX(-${index * sliderWidth}px)`;
            
            pageNum.textContent = `${index + 1} / ${totalSlides}`;
            dots.forEach((dot, i) => dot.classList.toggle('active', i === index));
        }

        // 브라우저 크기가 변할 때(resize) 슬라이더 위치를 재조정
        window.addEventListener('resize', updateUI);

        function nextSlide() {
            index = (index < totalSlides - 1) ? index + 1 : 0;
            updateUI();
        }

        function prevSlide() {
            index = (index > 0) ? index - 1 : totalSlides - 1;
            updateUI();
        }

        nextBtn.addEventListener('click', nextSlide);
        prevBtn.addEventListener('click', prevSlide);

        dots.forEach((dot, i) => {
            dot.addEventListener('click', () => {
                index = i;
                updateUI();
            });
        });

        function startAutoPlay() {
            if (!slideTimer) slideTimer = setInterval(nextSlide, 3000);
        }

        function stopAutoPlay() {
            clearInterval(slideTimer);
            slideTimer = null;
        }

        playPauseBtn.addEventListener('click', () => {
            if (isPlaying) {
                stopAutoPlay();
                playPauseBtn.textContent = 'PLAY';
            } else {
                startAutoPlay();
                playPauseBtn.textContent = 'PAUSE';
            }
            isPlaying = !isPlaying;
        });

        startAutoPlay();
        updateUI(); // 초기 위치 설정
    </script>
</body>
</html>

※ 해당 내용은 Google Gmini3.0에서 작성되었습니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함