小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
轮播图是一个常见的组件,今天用js来实现一个简单的轮播图。
功能如下:
- 自动轮播,有滑动效果。
- 左右箭头可实现上一张下一张的切换,并作了节流处理。
- 点击下方小圆点可切换至对应的图片。
- 鼠标悬停至图片或小圆点处会暂停轮播,移开则继续。
原理
如上图所示 ,以展示三张图且切换下一张为例。123数字代表图1,图2,图3,蓝色矩形框为可视范围,即轮播图展示的范围,其余图片均隐藏。
- 状态A:页面的初始状态,默认显示第一张图片。
- 状态B:整个图片列表向左移动,即可显示第二张图片。
- 状态C:同状态B。
- 状态D:此时又显示第一张图片(但对于图片列表而言是最后一张),需要切换为状态E即初始状态。切换的过程需要修改整个图片列表的left值,且过渡时间设为0s。
- 完成了一轮循环。切换上一张同理。
源码
HTML
<div class="wrap">
<div class="img-box">
<img src="1.jpg" alt="" class="image">
<img src="2.jpg" alt="" class="image">
<img src="3.jpg" alt="" class="image">
</div>
<div onclick="prev()" class="btn left"><img src="left.png" alt="" class="arrow"></div>
<div onclick="next()" class="btn right"><img src="right.png" alt="" class="arrow"></div>
<ul>
<li style="background-color: #333333;"></li>
<li></li>
<li></li>
</ul>
</div>
JS
const imgBox = document.querySelector('.img-box')
const imgs = document.querySelectorAll('.image')
const lis = document.querySelectorAll('li')
const activeColor = '#333333'
const defaultColor = 'rgb(204, 204, 204)'
imgBox.insertBefore(imgs[imgs.length-1].cloneNode(true),imgs[0])
imgBox.appendChild(imgs[0].cloneNode(true))
imgBox.style.transform = 'translateX(-880px)'
let now = 1
let timer = null
function next(){
//节流处理
if(!timer){
imgBox.style.transition = '1s'
imgBox.style.transform = `translateX(-${++now*880}px)`
for(let i = 0;i<imgs.length;i++){
if(i != now-1){
lis[i].style.backgroundColor = defaultColor
}
}
if(now > imgs.length)
lis[0].style.backgroundColor = activeColor
else
lis[now-1].style.backgroundColor = activeColor
timer = setTimeout(() => {
if(now > imgs.length){
now = 1
imgBox.style.transition = 'none'
imgBox.style.transform = `translateX(-${now*880}px)`
}
timer = null
}, 1000);
}
}
function prev(){
if(!timer){
imgBox.style.transition = '1s'
imgBox.style.transform = `translateX(-${--now*880}px)`
for(let i = 0;i<imgs.length;i++){
if(i != now-1){
lis[i].style.backgroundColor = defaultColor
}
}
if(now == 0)
lis[imgs.length-1].style.backgroundColor = activeColor
else
lis[now-1].style.backgroundColor = activeColor
timer = setTimeout(() => {
if(!now){
now = imgs.length
imgBox.style.transition = 'none'
imgBox.style.transform = `translateX(-${now*880}px)`
}
timer = null
}, 1000);
}
}
timerInt = setInterval(next,2000)
imgBox.onmouseover = function() {
clearInterval(timerInt)
}
imgBox.onmouseout = function() {
timerInt = setInterval(next,2000)
}
for(let k=0;k<imgs.length;k++){
lis[k].onmouseover = function() {
clearInterval(timerInt)
}
lis[k].onmouseout = function() {
timerInt = setInterval(next,2000)
}
lis[k].onclick = function(){
step = k + 1
imgBox.style.transform = `translateX(-${step*880}px)`
for(let i = 0;i<imgs.length;i++){
if(i != k){
lis[i].style.backgroundColor = defaultColor
}
}
lis[k].style.backgroundColor = activeColor
}
}
CSS
.wrap {
width: 880px;
height: 305px;
margin: 0 auto;
/* border: 1px solid #333333; */
position: relative;
overflow: hidden;
}
.img-box {
width: 880px;
display: flex;
position: absolute;
}
.btn {
position: absolute;
z-index: 1;
width: 50px;
height: 305px;
line-height: 305px;
text-align: center;
font-size: 16px;
color: #ffffff;
font-weight: bold;
cursor: pointer;
}
.btn:hover {
background-color: rgba(240, 240, 235, 0.575);
}
.left {
left: 0;
}
.right {
right: 0;
}
.arrow {
width: 15px;
height: 15px;
}
.wrap ul{
padding: 0;
list-style: none;
width: 880px;
height: 15px;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
bottom: 10px;
z-index: 1;
}
.wrap ul li {
width: 15px;
height: 15px;
border-radius: 50%;
background-color:rgb(204, 204, 204);
margin: 0 5px;
}
实现效果
需要注意的地方
- 首尾各加一张图的目的是为了初次点击时能有好的过渡效果,并且更便于背后的操作。
- 一定要等过渡完成后才进行移动的暗箱操作,所以会使用延时器setTimeout,且时延===过渡时间。
- 为防止用户点击速度过快,一定要进行节流处理。