HTML+CSS+JavaScript实现轮播图效果
前言
先奉上本文需要的所有资源,免费下载,代码有详细注释,可搭配本文使用:
百度网盘:百度网盘 请输入提取码
提取码:slbt
没有添加动画效果,添加了自动切换和手动切换功能。
效果演示:
功能介绍:
-
页面加载后,每隔两秒就切换下一张图片
-
点击上一张和下一张按钮可以循环切换
-
点击小圆点可以指定切换
-
鼠标放在图片上停止切换,移开后等待两秒继续自动切换
关键功能由定时器实现,如果对定时器不了解的朋友,可以看看我之前写的文章:
我们将本案例拆分成三个部分来讲解。
HTML
HTML 部分比较简单,直接由注释来讲解:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>轮播图效果</title>
<!-- 引入外部样式文件 -->
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- 大容器 -->
<div class="slideshow">
<!-- 图片展示 -->
<div class="image">
<!-- 通过js改变src属性值替换图片 -->
<img src="./image/1.png" id="img-show">
</div>
<!-- 上一张按钮 -->
<div class="previous" id="to-pre">❮</div>
<!-- 下一张按钮 -->
<div class="next" id="to-next">❯</div>
<!-- 自由选择小圆点 -->
<div class="dots" id="dot-container">
<!-- 小圆点由 js 动态生成 -->
</div>
</div>
<!-- 引入外部脚本文件 -->
<script src="./slide.js"></script>
</body>
</html>
CSS
CSS 部分也比较简单,直接由注释来讲解:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: rgb(254, 202, 211);
}
/* 大容器实现水平垂直居中 */
.slideshow {
position: absolute; /* 绝对定位 */
top: 50%; /* 向下偏移窗口高度的50% */
left: 50%; /* 向右偏移窗口长度的50% */
width: 700px;
/*
由于上面的偏移位置是由当前元素的左上角决定,注释下面一句代码查看会发生什么问题,
下面这句代码是以当前元素的宽高向上向左移动50%,联合上面的偏移实现水平垂直居中。
*/
transform: translate(-50%, -50%);
}
.slideshow .image {
width: 100%;
}
.slideshow .image>img {
display: block; /* 去除图片底部的空白 */
width: 100%; /* 让图片的宽始终的等于父元素的宽 */
}
/* 切换按钮 */
.slideshow .previous,
.slideshow .next {
position: absolute;
/* 下面两句实现切换按钮垂直居中 */
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
margin-left: 5px;
border-radius: 20px;
background-color: rgba(0, 0, 0, 0.5);
font: 700 20px/2 "Arial";
color: white;
text-align: center;
}
.slideshow .next {
right: 5px; /* 将下一张按钮移到右边 */
}
.slideshow .previous:hover,
.slideshow .next:hover {
cursor: pointer;
background-color: rgba(0, 0, 0, 0.7);
}
/* 放置小圆点的容器,不给它设置宽度,让它可以动态添加小圆点 */
.slideshow .dots {
position: absolute;
bottom: 20px; /* 从底部向上偏移20px */
/* 下面两句让小圆点容器实现水平居中 */
left: 50%;
transform: translateX(-50%);
}
.slideshow .dots:hover {
cursor: pointer;
}
/* 小圆点样式 */
.dot {
display: inline-block;
width: 16px;
height: 16px;
margin: 0px 4px;
border-radius: 8px;
background-color: white;
}
.dot:hover {
cursor: pointer;
background-color: rgb(72, 72, 72);
}
/* 小圆点对应的图片被展示时,小圆点变灰 */
.dots .selected {
background-color: rgb(72, 72, 72);
}
JavaScript
轮播图的实现关键就在于 JavaScript 代码,下面详细介绍这一部分,建议对照源文件的代码!
生成小圆点:
首先,需要获取所有图片的路径。这里把路径存入数组中,之后可以根据数组的长度来动态的创建小圆点:
const images = ['./image/1.png', './image/2.jpg', './image/3.jpg', './image/4.jpg', './image/5.jpg', './image/6.png'];
利用这个数组来动态的创建小圆点,在这之前,需要先获得容纳小圆点的容器:
let dotContainer = document.getElementById("dot-container");
// 根据数组images的长度获取图片张数,并动态创建小圆点
for(let i=0; i<images.length; i++) {
let dot = document.createElement("span"); // 创建小圆点
dot.className = "dot"; // 为创建的小圆点设置类名
dot.id = "dot"+i; // 为创建的小圆点设置id
// 将创建的小圆点添加到小圆点容器中
dotContainer.appendChild(dot);
}
完成上述代码后,底部会出现多个小圆点,效果如下:
第一张图片出现时,它所对应的小圆点应该会变成灰色。要实现这种效果,可以加入下面一段代码:
let defaultDot = document.getElementById("dot0").className = "dot selected";
这句话出现在全局作用域中,因此页面加载时,第一张图片的小圆点就会变成灰色。通过改变元素的类属性值实现!
当所有小圆点都被创建后,我们需要通过类名获取它们,之后你便会知道为什么这么做:
let dots = document.getElementsByClassName("dot");
接下来要用到定时器,因为我们要实现自动切换效果。
自动切换:
页面加载后,我们让图片每隔两秒切换一次,于是需要在全局作用域中添加一个定时器。用变量 t 来保存定时任务的标识符,t 需要在全局作用域中添加:
t = setTimeout( ()=>{
timer();
}, 1000*2);
timer() 是我们自己定义的一个函数,这是它内部的代码:
function timer() {
changeImage(false); // 调用图片切换函数
// 图片切换后重新设置一个定时器
t = setTimeout( ()=>{ timer(); }, 1000*2);
}
页面加载到定时器时,定时器会在两秒后执行回调函数。接下来回调函数中的 timer() 函数会被执行,在 timer() 内部,图片切换函数会被调用,调用完成后再重新设置一个定时器。因为 setTimeout() 是一次性的,页面加载时的定时器已经结束了,所以需要重新创建定时器。而重新创建的定时器又会调用自身所在的函数,于是每隔两秒会进入一次循环。如果有不理解的朋友,建议先去了解一下定时器。
我们再看看图片切换函数是什么样的,这个函数也会被前后切换按钮调用,通过判断传入的是 true 还是 false 来执行前后切换。还记得前面说过当所有小圆点都被创建后,我们需要通过类名获取它们,获取它们后,我们就可以通过索引的方式访问我们想访问的那个小圆点,在更改小圆点样式的时候非常有用。这里的 imgNow 是一个全局变量,记得在全局作用域中添加这个变量,用来标记当前展示的是第几张图片:
// 图片切换函数,传入布尔值,true:前一张, false:后一张
function changeImage(direction) {
// 先通过循环让所有小圆点样式恢复初始值(白色)
for(let i=0; i<dots.length; i++) {
dots[i].className = "dot";
}
// 判断是向前切换还是向后切换
if(direction) {
if(imgNow == 0) {
// 如果是第一张继续向前切换,则被切换到最后一张形成循环
imgNow = images.length-1;
} else {
imgNow -= 1;
}
// 切换图片
document.getElementById("img-show").src = images[imgNow];
// 将当前图片的小圆点变灰
dots[imgNow].className = "dot selected";
} else {
if(imgNow == images.length-1) {
// 如果是最后一张继续向后切换,则被切换到第一张形成循环
imgNow = 0;
} else {
imgNow += 1;
}
document.getElementById("img-show").src = images[imgNow];
dots[imgNow].className = "dot selected";
}
}
以上所有代码就已经实现了文章开头演示的效果。
前后切换:
接下来实现前后按钮切换效果,我们需要给这两个按钮添加事件监听器:
let previous = document.getElementById("to-pre");
previous.addEventListener("click", function() {
clearTimeout(t); // 先清除定时器
changeImage(true); // true 向前切换图片
t = setTimeout( ()=>{ timer(); }, 1000*2); // 重新创建一个定时器
});
let next = document.getElementById("to-next");
next.addEventListener("click", function() {
clearTimeout(t);
changeImage(false);
t = setTimeout( ()=>{ timer(); }, 1000*2);
});
点击切换按钮时,之前没有结束的定时器会被立即取消,并调用图片切换函数实现图片切换,图片切换后,再重新添加计时器让页面自动切换。
自由切换:
自由切换是由点击小圆点实现的,因此我们也需要给小圆点添加事件监听器。将之前生成小圆点的代码稍微修改就可以了:
for(let i=0; i<images.length; i++) {
let dot = document.createElement("span"); // 创建小圆点
dot.className = "dot"; // 为创建的小圆点设置类名
dot.id = "dot"+i; // 为创建的小圆点设置id
// 给小圆点添加监听事件
dot.addEventListener("click", function() {
// 先清除之前的定时器
clearTimeout(t);
dotID = this.getAttribute("id"); // 获取当前小圆点的id
imgNow = Number(dotID.replace("dot", "")); // 取出id里的数字
document.getElementById("img-show").src = images[imgNow]; // 显示指定的图片
// 将所有小圆点的样式设置成默认
for(let i=0; i<dots.length; i++) {
dots[i].className = "dot";
}
// 再将当前被选中的小圆点颜色变为灰色, 这里通过给它添加两个类实现
this.className = "dot selected";
// 设置定时器,两秒后再切换下一张
t = setTimeout( ()=>{ timer(); }, 1000*2);
});
// 将创建的小圆点添加到小圆点容器中
dotContainer.appendChild(dot);
}
在循环创建小圆点的同时,就给每个小圆点添加事件监听器,是不是很方便!
暂停自动切换:
接下来实现当鼠标停留在图片上时,停止切换,鼠标挪开两秒后继续切换。这需要给图片添加事件监听器。
document.getElementById("img-show").addEventListener("mouseover", function() {
clearTimeout(t); // 鼠标移入时取消定时器
});
document.getElementById("img-show").addEventListener("mouseout", function() {
t = setTimeout( ()=>{ timer(); }, 1000*2); // 鼠标移出时重新添加计时器
});
完成所有任务后,轮播图的效果就制作完成了!
JavaScript 源代码:
const images = ['./image/1.png', './image/2.jpg', './image/3.jpg', './image/4.jpg', './image/5.jpg', './image/6.png'];
let imgNow = 0;
let t;
let dotContainer = document.getElementById("dot-container");
for(let i=0; i<images.length; i++) {
let dot = document.createElement("span");
dot.className = "dot";
dot.id = "dot"+i;
dot.addEventListener("click", function() {
clearTimeout(t);
dotID = this.getAttribute("id");
imgNow = Number(dotID.replace("dot", ""));
document.getElementById("img-show").src = images[imgNow];
for(let i=0; i<dots.length; i++) {
dots[i].className = "dot";
}
this.className = "dot selected";
t = setTimeout( ()=>{ timer(); }, 1000*2);
});
dotContainer.appendChild(dot);
}
let defaultDot = document.getElementById("dot0").className = "dot selected";
let dots = document.getElementsByClassName("dot");
t = setTimeout( ()=>{
timer();
}, 1000*2);
document.getElementById("img-show").addEventListener("mouseover", function() {
clearTimeout(t);
});
document.getElementById("img-show").addEventListener("mouseout", function() {
t = setTimeout( ()=>{ timer(); }, 1000*2);
});
let previous = document.getElementById("to-pre");
previous.addEventListener("click", function() {
clearTimeout(t);
changeImage(true);
t = setTimeout( ()=>{ timer(); }, 1000*2);
});
let next = document.getElementById("to-next");
next.addEventListener("click", function() {
clearTimeout(t);
changeImage(false);
t = setTimeout( ()=>{ timer(); }, 1000*2);
});
function timer() {
changeImage(false);
t = setTimeout( ()=>{ timer(); }, 1000*2);
}
function changeImage(direction) {
for(let i=0; i<dots.length; i++) {
dots[i].className = "dot";
}
if(direction) {
if(imgNow == 0) {
imgNow = images.length-1;
} else {
imgNow -= 1;
}
document.getElementById("img-show").src = images[imgNow];
dots[imgNow].className = "dot selected";
} else {
if(imgNow == images.length-1) {
imgNow = 0;
} else {
imgNow += 1;
}
document.getElementById("img-show").src = images[imgNow];
dots[imgNow].className = "dot selected";
}
}
结语
轮播图的效果有很多种,做起来也挺有意思。本文所做的轮播图没有添加动画效果,适合不会做动画的初学者参考。如果对动画感兴趣,之后我也会分享添加了动画效果的轮播图。
更多推荐
所有评论(0)