iT邦幫忙

2021 iThome 鐵人賽

DAY 15
0
Modern Web

30天30個前端任務系列 第 17

#17. Image Carousel(原生JS版)

今天要分享的專案是照片輪播UI,也就是俗稱的Carousel。
Carousel可以框架實現,像是Bootstraps和Swiper.js,但要怎麼自己手刻一個呢?

實作邏輯

  1. 在一個設定Overflow Hidden的內置入div.image-container,裡面放置多張圖片,由於外層會隱藏內容外溢的部分,因此會產生遮罩的效果,只看得到一張圖片(若圖片寬度與最外層一樣的話)。
  2. 運用transform: translateX將div.image-container橫移,自然就會帶到另一張圖片。
  3. 運用JS來改變div.image-container的位置。

Carousel本身有很多形式,比較常見的有自動輪播和按鈕控制上下一張。這次手刻的Carousel把兩個寫在一起,作為刻意練習。

實作成果請參考CodePen

html

<div class="carousel">
  <div class="image-container" id="imgs">
    <img src="略..."
       alt="first-image"
    />
    <img
       src="略..."
       alt="second-image"
    />
    <img
       src="略..."
       alt="third-image"
    />
    <img
       src="略..."
       alt="fourth-image"
    />
  </div>
 <div class="buttons-container">
   <button id="left" class="btn">Prev</button>
   <button id="right" class="btn">Next</button>
 </div>
</div>

CSS

img {
  width: 500px;
  height: 500px;
  object-fit: cover;
}

.carousel {
  box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
  height: 530px;
  width: 500px;
  // 將image-container溢出的內容隱藏起來
  overflow: hidden;
}

.image-container {
  display: flex;
  // 設定translateX的起始點,之後透過JS來改變
  transform: translateX(0);
  transition: transform 0.5s ease-in-out;
}

.buttons-container {
  display: flex;
  justify-content: space-between;
}

.btn {
  background-color: rebeccapurple;
  color: #fff;
  border: none;
  padding: 0.5rem;
  cursor: pointer;
  width: 49.5%;
}

Javascript

const imgs = document.getElementById('imgs')
const leftBtn = document.getElementById('left')
const rightBtn = document.getElementById('right')
const img = document.querySelectorAll('#imgs img')

let idx = 0

// 每兩秒執行函式run一次
let interval = setInterval(run, 2000)

// idx+1,然後執行changeImage函式
function run() {
    idx++
    changeImage()
}

// 比對idx和img陣列的長度,然後判斷要輸出什麼值來套用translateX屬性
function changeImage() {
    // 由於array.length是從1開始計算,跟index的起始數字不同,因此img.length要 - 1
    if(idx > img.length - 1) {
        idx = 0
      // 避免prev按鈕行為讓idx小於零
    } else if(idx < 0) {
        idx = img.length - 1
    }
    // 從這行translateX可以判斷,idx最初必須為零,然後要顯示最後一張圖片,idx不能大於img.length
    imgs.style.transform = `translateX(${-idx * 500}px)`
}

// next按鈕行為,先改變圖片位置,兩秒後再重啟計時器。
rightBtn.addEventListener('click', () => {
    idx++
    changeImage()
    resetInterval()
})

// prev按鈕行為
leftBtn.addEventListener('click', () => {
    idx--
    changeImage()
    resetInterval()
})

// 重設計時器
function resetInterval() {
    clearInterval(interval)
    interval = setInterval(run, 2000)
}

上一篇
#16. Quiz App(Vue版)
下一篇
#18. Fixed Navbar(原生JS版)
系列文
30天30個前端任務19

尚未有邦友留言

立即登入留言