下面是针对JS原生手写轮播图效果的完整攻略:
一、需求分析
首先要清楚地明确轮播图的需求,包括:
- 显示多张图片并自动轮播;
- 支持点击左侧和右侧按钮来切换图片;
- 支持点击数字按钮来跳转到相应的图片;
- 支持鼠标悬停在图片上时停止轮播,离开时继续轮播。
二、实现步骤
然后根据需求来逐步实现轮播图效果,具体步骤如下:
-
编写HTML结构;
-
设置相应的样式;
-
使用JS实现轮播图的自动播放效果;
-
使用JS实现点击按钮切换图片的效果;
-
使用JS实现点击数字按钮跳转到相应图片的效果;
-
实现鼠标悬停在图片上时轮播停止的效果。
2.1 HTML结构
首先,按照轮播图的需求,编写HTML结构。通常可以采用以下结构:
<div class="slider">
<div class="slider-wrapper">
<div class="slider-item"><img src="image1.jpg"></div>
<div class="slider-item"><img src="image2.jpg"></div>
<div class="slider-item"><img src="image3.jpg"></div>
</div>
<ul class="slider-nav">
<li class="slider-nav-item">1</li>
<li class="slider-nav-item">2</li>
<li class="slider-nav-item">3</li>
</ul>
<a class="slider-control prev"></a>
<a class="slider-control next"></a>
</div>
这段HTML代码中,.slider
是整个轮播图的容器,包括一个.slider-wrapper
用来包裹所有的图片,并设置overflow:hidden
来隐藏溢出的部分;还有一个.slider-nav
用来放置数字按钮;以及两个.slider-control
分别表示向左、向右的箭头。
2.2 设置样式
接下来,需要设置轮播图的样式。通过CSS设置轮播图样式可以更好地控制UI,提供更好的用户体验。
.slider {
position: relative;
width: 100%;
height: 400px;
}
.slider-wrapper {
width: 300%;
height: 400px;
position: relative;
left: 0;
transition: left .5s;
}
.slider-item {
float: left;
width: 33.3333%;
height: 400px;
text-align: center;
font-size: 40px;
color: #fff;
background-color: #000;
}
.slider-item img {
max-width: 100%;
max-height: 100%;
}
.slider-nav {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
margin: 0;
padding: 0;
list-style: none;
z-index: 1;
}
.slider-nav-item {
display: inline-block;
margin-right: 10px;
border: 2px solid #fff;
width: 20px;
height: 20px;
border-radius: 50%;
text-align: center;
line-height: 20px;
color: #fff;
cursor: pointer;
}
.slider-nav-item.active {
background-color: #fff;
color: #000;
}
.slider-control {
position: absolute;
top: 50%;
margin-top: -20px;
width: 40px;
height: 40px;
background-color: #fff;
cursor: pointer;
z-index: 1;
}
.slider-control.prev {
left: 20px;
}
.slider-control.next {
right: 20px;
}
上面这段CSS代码主要做的事情是:
- 定义了整个轮播图容器
.slider
的宽度、高度等样式; - 设定了
.slider-wrapper
中每个.slider-item
的宽度、高度等样式,并设置.slider-item img
的最大宽度和高度为100%,以使图片按比例自适应大小; - 定义了数字按钮
.slider-nav-item
的样式,设置外边距、边框、圆角、文字对齐、鼠标样式等属性,以及.slider-nav-item.active
的样式,表示当前选中的按钮; - 定义了向左和向右箭头
.slider-control
的样式,设置位置、大小、背景色和鼠标样式等属性。
2.3 实现轮播图自动播放
了解了上面的基本结构和样式,接下来就要开始在JS中实现轮播图自动播放。可以采用如下代码实现:
var timer = null;
var index = 0;
var items = document.querySelectorAll('.slider-item');
var len = items.length;
var navItems = document.querySelectorAll('.slider-nav-item');
function slideNext() {
index++;
if (index >= len) {
index = 0;
}
slideTo(index);
}
function slideTo(i) {
var offset = -i * 100 / len;
document.querySelector('.slider-wrapper').style.left = offset + '%';
setActiveNav(i);
}
function setActiveNav(i) {
[].forEach.call(navItems, function(navItem) {
navItem.classList.remove('active');
});
navItems[i].classList.add('active');
}
timer = setInterval(slideNext, 3000);
上面这段代码中,主要做的事情是:
- 定义了一个
timer
变量,用来保存定时器的ID; - 定义了
index
变量,表示当前轮播图显示的是第几张; - 通过
document.querySelectorAll
获取了所有的轮播图图片.slider-item
和数字按钮.slider-nav-item
; - 定义了
slideNext
方法和slideTo
方法; slideNext
方法用于自动轮播的逻辑,其内部先将索引index
自增,然后检查是否超过图片数量,如果超过了就将index
重置为0;接下来调用slideTo
方法,将图片滑动到指定位置;slideTo
方法根据当前要显示的图片索引,计算出需要滑动的偏移量offset
,然后设置图片盒子.slider-wrapper
的左偏移量为offset + '%'
,以实现滑动效果;接着调用setActiveNav
方法,将当前数字按钮设置为选中状态;setActiveNav
方法用来设置数字按钮的选中状态。首先使用[].forEach.call
将数字按钮遍历一遍,将所有的数字按钮都设置为非选中状态;然后将当前要选中的数字按钮设置为选中状态。
2.4 实现点击按钮切换图片的效果
接下来,我们需要实现点击左右箭头切换图片的效果。这可以通过绑定事件来实现,以下是实现代码:
var prevBtn = document.querySelector('.slider-control.prev');
var nextBtn = document.querySelector('.slider-control.next');
prevBtn.addEventListener('click', function() {
clearInterval(timer);
index--;
if (index < 0) {
index = len - 1;
}
slideTo(index);
timer = setInterval(slideNext, 3000);
});
nextBtn.addEventListener('click', function() {
clearInterval(timer);
index++;
if (index >= len) {
index = 0;
}
slideTo(index);
timer = setInterval(slideNext, 3000);
});
该代码中主要做的事情是:
- 获取左箭头和右箭头
.slider-control
; - 为左箭头绑定一个点击事件
prevBtn.addEventListener('click', function() { ... });
; - 为右箭头绑定一个点击事件
nextBtn.addEventListener('click', function() { ... });
; - 点击左箭头需要暂停自动播放,并且将当前显示的图片索引
index
减1,如果小于0则重置为最大索引值;接着执行slideTo(index)
将图片显示到指定位置,并重新启动自动播放。右箭头同理。
2.5 实现点击数字按钮跳转到相应图片的效果
上述代码中,我们已经实现了自动播放和点击箭头切换图片的效果。但是,还需要实现点击数字按钮跳转到相应图片的效果。与点击箭头切换图片类似,也是绑定一个点击事件来实现,以下是实现代码:
[].forEach.call(navItems, function(navItem, i) {
navItem.addEventListener('click', function() {
clearInterval(timer);
index = i;
slideTo(index);
timer = setInterval(slideNext, 3000);
});
});
该代码主要做的事情是:
- 使用
[].forEach.call
遍历所有数字按钮; - 对于每个按钮,绑定一个点击事件
navItem.addEventListener('click', function() { ... });
; - 点击数字按钮需要暂停自动播放,并且将当前显示的图片索引
index
设置为该按钮的索引i
;接着执行slideTo(index)
将图片滑动到指定位置,并重新启动自动播放。
2.6 实现鼠标悬停时轮播停止的效果
最后一个需求是实现当鼠标悬停在轮播图上时,自动轮播停止,离开时继续轮播的效果。这也可以通过绑定事件来实现,实现代码如下:
var slider = document.querySelector('.slider');
slider.addEventListener('mouseover', function() {
clearInterval(timer);
});
slider.addEventListener('mouseout', function() {
timer = setInterval(slideNext, 3000);
});
该代码中主要做的事情是:
- 获取轮播图容器
.slider
; - 为
.slider
绑定一个鼠标悬停事件slider.addEventListener('mouseover', function() { ... });
; - 为
.slider
绑定一个鼠标离开事件slider.addEventListener('mouseout', function() { ... });
; - 鼠标悬停在轮播图上时,需要暂停自动轮播;离开时,重新启动自动轮播。
这样就完成了所有的需求。
三、示例说明
下面简单介绍两个示例:
示例一
示例一是一个基本版的轮播图,将所有代码放在一个完整的HTML文件中。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS原生轮播图示例</title>
<style>
.slider {
position: relative;
width: 100%;
height: 400px;
}
.slider-wrapper {
width: 300%;
height: 400px;
position: relative;
left: 0;
transition: left .5s;
}
.slider-item {
float: left;
width: 33.3333%;
height: 400px;
text-align: center;
font-size: 40px;
color: #fff;
background-color: #000;
}
.slider-item img {
max-width: 100%;
max-height: 100%;
}
.slider-nav {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
margin: 0;
padding: 0;
list-style: none;
z-index: 1;
}
.slider-nav-item {
display: inline-block;
margin-right: 10px;
border: 2px solid #fff;
width: 20px;
height: 20px;
border-radius: 50%;
text-align: center;
line-height: 20px;
color: #fff;
cursor: pointer;
}
.slider-nav-item.active {
background-color: #fff;
color: #000;
}
.slider-control {
position: absolute;
top: 50%;
margin-top: -20px;
width: 40px;
height: 40px;
background-color: #fff;
cursor: pointer;
z-index: 1;
}
.slider-control.prev {
left: 20px;
}
.slider-control.next {
right: 20px;
}
</style>
</head>
<body>
<div class="slider">
<div class="slider-wrapper">
<div class="slider-item"><img src="https://picsum.photos/800/400?image=1"></div>
<div class="slider-item"><img src="https://picsum.photos/800/400?image=2"></div>
<div class="slider-item"><img src="https://picsum.photos/800/400?image=3"></div>
</div>
<ul class="slider-nav">
<li class="slider-nav-item active">1</li>
<li class="slider-nav-item">2</li>
<li class="slider-nav-item">3</li>
</ul>
<a class="slider-control prev"></a>
<a class="slider-control next"></a>
</div>
<script>
var timer = null;
var index = 0;
var items = document.querySelectorAll('.slider-item');
var len = items.length;
var navItems = document.querySelectorAll('.slider-nav-item');
function slideNext() {
index++;
if (index >= len) {
index = 0;
}
slideTo(index);
}
function slideTo(i) {
var offset = -i * 100 / len;
document.querySelector('.slider-wrapper').style.left = offset + '%';
setActiveNav(i);
}
function setActiveNav(i) {
[].forEach.call(navItems, function(navItem) {
navItem.classList.remove('active');
});
navItems[i].classList.add('active');
}
var prevBtn = document.querySelector('.slider-control.prev');
var nextBtn = document.querySelector('.slider-control.next');
prevBtn.addEventListener('click', function() {
clearInterval(timer);
index--;
if (index < 0) {
index = len - 1;
}
slideTo(index);
timer = setInterval(slideNext, 3000);
});
nextBtn.addEventListener('click', function() {
clearInterval(timer);
index++;
if (index >= len) {
index = 0;
}
slideTo(index);
timer = setInterval(slideNext, 3000);
});
[].forEach.call(navItems, function(navItem, i) {
navItem.addEventListener('click', function() {
clearInterval(timer);
index = i;
slideTo(index);
timer = setInterval(slideNext, 3000);
});
});
var slider = document.querySelector('.slider');
slider.addEventListener('mouseover', function() {
clearInterval(timer);
});
slider.addEventListener('mouseout', function() {
timer = setInterval(slideNext, 3000);
});
timer = setInterval(slideNext, 3000);
</script>
</body>
</html>
示例二
示例二是一个稍微复杂一些的轮播图,将JS代码单独拆分成一个文件,并添加了一些CSS3动画效果。
首先,创建一个index.html
文件,代码如下:
```html