iT邦幫忙

2025 iThome 鐵人賽

DAY 17
0

目標

因為昨天修改了專輯展示區的內容,所以今天要一併修改滑動效果,達到以下效果:

  1. 當最後一個專輯或 MV 出現在最右邊時,右邊箭頭不能再點擊。
  2. 專輯展示區及 MV 展示區滑動效果相同,因此統一成通用函式,方便維護與重複使用。

程式碼說明

將兩個輪播區統一成一個 createCarousel 函式,只需傳入對應的參數即可使用:

// 通用輪播函式
function createCarousel({ trackId, prevBtnId, nextBtnId, cardSelector, gap }) {
    const track = document.getElementById(trackId);
    const prevBtn = document.getElementById(prevBtnId);
    const nextBtn = document.getElementById(nextBtnId);
    const cards = document.querySelectorAll(cardSelector);


    let currentIndex = 0;


    // 計算卡片寬度(含 gap)
    function getCardWidth() {
        const cardRect = cards[0].getBoundingClientRect();
        return cardRect.width + gap;
    }


    // 計算螢幕可見卡片數
    function getVisibleCards() {
        const containerWidth = track.parentElement.getBoundingClientRect().width;
        const cardWidth = getCardWidth();
        return Math.floor(containerWidth / cardWidth);
    }


    // 更新輪播位置
    function updateCarousel() {
        const cardWidth = getCardWidth();
        const visibleCards = getVisibleCards();
        const maxIndex = cards.length - visibleCards -1; // 最大索引


        // 限制 currentIndex 範圍
        if (currentIndex > maxIndex) currentIndex = maxIndex;
        if (currentIndex < 0) currentIndex = 0;


        track.style.transform = `translateX(-${currentIndex * cardWidth}px)`;


        // 更新按鈕狀態
        prevBtn.disabled = currentIndex === 0;
        nextBtn.disabled = currentIndex === maxIndex;
    }


    // 按鈕事件
    nextBtn.addEventListener('click', () => {
        currentIndex++;
        updateCarousel();
    });


    prevBtn.addEventListener('click', () => {
        currentIndex--;
        updateCarousel();
    });


    // 初始化 + 視窗大小改變時更新
    updateCarousel();
    window.addEventListener('resize', updateCarousel);
}




// -----------------------------
// 使用通用函式初始化輪播
// -----------------------------


// 專輯展示區
createCarousel({
    trackId: 'carouselTrack',
    prevBtnId: 'prevBtn',
    nextBtnId: 'nextBtn',
    cardSelector: '.album-card',
    gap: 16
});


// MV 展示區
createCarousel({
    trackId: 'mvCarouselTrack',
    prevBtnId: 'mvPrevBtn',
    nextBtnId: 'mvNextBtn',
    cardSelector: '.mv-card',
    gap: 20
});

程式碼說明重點

  1. 函式封裝

    • 每個輪播區都是獨立作用域,變數互不干擾,避免 MV 與專輯輪播互相覆蓋造成無法滑動的問題。
  2. 自適應螢幕

    • 使用 getVisibleCards() 自動計算可見卡片數,當螢幕縮放時,自動更新輪播,不需要寫死顯示 5 張或其他數量。
  3. 滑動限制

    • maxIndex = cards.length - visibleCards - 1 確保最後一張卡片靠右時停止滑動,不會出現半張卡露出的狀況。
  4. 按鈕狀態更新

    • 左右箭頭會根據 currentIndex 自動禁用,提升使用者體驗。
  5. 可重複使用

    • 只要傳入不同的 DOM ID 與卡片選擇器,MV 與專輯展示區都能使用同一套程式碼,維護成本低。

上一篇
改良專輯展示區的互動效果
下一篇
製作單曲展示區
系列文
打造專屬於歌手的音樂資訊網頁:從零開始的前端實作與技術分享19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言