#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)
}

<<:  SystemC: 月球转运站

>>:  Day 3 ROS 安装

Day 20 - Self-defined Data types(in C) 自订资料型态

Intro 自订资料型态可以是 把不同 data type 合成成一个 复合的型态 或是重新定义一个...

豆技巧到底实用不实用呢?

豆知识是指各种很琐碎、不成系统、缺乏逻辑连贯性的零碎条目知识。 像「随便在自己启动的Thread中更...

用React刻自己的投资Dashboard Day24 - styled components

tags: 2021铁人赛 React 因为下一篇要让导览列在手机版网页呈现汉堡选单的样式,在参考其...

D27 / 怎麽测试? - Testing Compose

今天大概会聊到的范围 Testing Compose 的 Test 属於 UI Test ,在执行...

Day 2 | 游戏发想过程

主题发想 最一开始我们希望做一个以妖怪为主题的AR游戏,经过讨论以及资料收集後,发现山海经里的神兽与...