使用原生js实现轮播图

使用原生JS实现轮播图,下面先看看成品;

实现的效果

  1. 图片自动滑动切换,鼠标移动到图片上则停止切换;
  2. 鼠标移动到圆点时切换到相应的图片;
  3. 点击箭头切换到下一张图片;
  4. 鼠标离开图片,则隐藏箭头;
  5. 默认是3张图片,需要更多图片时,只需追加<img>标签;

实现逻辑

将图片连接成条形,像胶卷一样,给个图片大小的窗口,左右移动图片条,完成切换;

实现代码

HTML

基本的HTML框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>轮播图</title>
<link rel="stylesheet" href="css/slide.css">
</head>
<body>
<div class="box">
<div id="pic_box">
<img src="img/arrow_left.png" id="arrow-left">
<img src="img/arrow_right.png" id="arrow-right">
<!--放圆点用-->
<ul id="multi-circles"></ul>
<div id="multi-images">
<img src="img/1.jpg"><img src="img/2.jpg"><img src="img/3.jpg">
</div>
</div>
</div>
<script src="js/slide.js"></script>
</body>
</html>

CSS

使用绝对定位对各个元素布局。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*定义图片大小与默认图片数*/
:root {
--imageWidth: 800px;
--imageHeight: 240px;
--imageNum: 3;
}

.box {
margin: 0 auto;
width: 800px;
}
/*只显示图片大小的窗口展示单张图片*/
#pic_box {
position: relative;
width: var(--imageWidth);
height: var(--imageHeight);
overflow: hidden;
}
/*绝对定位圆点的位置*/
#multi-circles {
position: absolute;
right: 30px;
bottom: 10px;
z-index: 2;
}
/*设置圆点的格式并使圆点横排*/
#multi-circles li {
width: 25px;
list-style: none;
font-size: 24px;
float: left;
color: white;
}
/*设置计算图片条的长度*/
#multi-images {
position: absolute;
left: 0;
top: 0;
z-index: 1;
width: calc(var(--imageWidth) * var(--imageNum));
height: var(--imageHeight);
transition: 1s;
}
/*设置左右箭头图标的位置*/
#arrow-right, #arrow-left {
position: absolute;
top: 50%;
margin-top: -24px;
height: 48px;
z-index: 3;
background: rgba(159, 180, 179, 0.38);
display: none;
cursor: pointer;
}

#arrow-right {
right: 0;
}

#arrow-left {
left: 0;
}

JS

核心步骤:

  1. 获取图片个数。
  2. 添加圆点。
  3. 设置“图片条”长度。
  4. 添加圆点、箭头的鼠标与点击事件;
  5. 设置图片轮播定时器;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//获得html组件
var arrowLeft = document.getElementById("arrow-left");
var arrowRight = document.getElementById("arrow-right");
var multiImages = document.getElementById("multi-images");
var circles = document.getElementById("multi-circles");
var picBox = document.getElementById("pic_box");
//图片个数
var picNum = multiImages.getElementsByTagName("img").length;
//根据图片数量添加圆点
for (var i = 0; i < picNum; i++) {
var liElement = document.createElement("li");
liElement.innerHTML = "●";
circles.appendChild(liElement);
}
//在html设置图片数量
document.documentElement.style.setProperty("--imageNum", picNum);
//获取css中设置的图片宽度
var imageWidth = getComputedStyle(document.documentElement).getPropertyValue("--imageWidth");
imageWidth = imageWidth.substring(0, imageWidth.indexOf("px"));
//设置轮播图片总长度
multiImages.style.width = picNum * imageWidth + "px";
//获取li列表对象
circles = document.getElementById("multi-circles").getElementsByTagName("li");
//最大下标
var maxIndex = picNum - 1;

//当前图片的序号
var currentIndex = 0;
//为箭头和圆点绑定事件
arrowLeft.addEventListener("click", preMove);
arrowRight.addEventListener("click", nextMove);
for (var i = 0; i < circles.length; i++) {
circles[i].setAttribute("id", i);
circles[i].addEventListener("mouseenter", overCircle);
}
//第一次载入,第一个圆是红色
circles[0].style.color = "#ff0000";
//定时器,每2秒移动
var time = setInterval(nextMove, 2000);

//滑过圆点
function overCircle() {
var preIndex = currentIndex;
currentIndex = parseInt(this.id);
moveImage();
changeCircleColor(preIndex, currentIndex)
}

//左箭头
function preMove() {
var preIndex = currentIndex;
if (currentIndex !== 0) {
currentIndex--;
} else {
currentIndex = maxIndex;
}
moveImage();
changeCircleColor(preIndex, currentIndex)
}

//右箭头
function nextMove() {
var preIndex = currentIndex;
if (currentIndex !== maxIndex) {
currentIndex++;
} else {
currentIndex = 0;
}
moveImage();
changeCircleColor(preIndex, currentIndex)
}

//移动图片
function moveImage() {
multiImages.style.left = -currentIndex * imageWidth + "px";
}

//改变圆点颜色
function changeCircleColor(preIndex, currentIndex) {
circles[preIndex].style.color = "#ffffff";
circles[currentIndex].style.color = "#ff0000"
}

//鼠标移动到图片上时显示箭头
picBox.addEventListener("mouseover", function (ev) {
arrowRight.style.display = "block";
arrowLeft.style.display = "block";
clearInterval(time);
});
//鼠标离开图片上时隐藏箭头
picBox.addEventListener("mouseleave", function (ev) {
arrowRight.style.display = "none";
arrowLeft.style.display = "none";
time = setInterval(nextMove, 2000);
});

遇到的bug

  1. 第二张图片显示不完整,而且左边有白边,而第三张图片不显示。

  在浏览器中检查发现两张图片之间有缝隙,导致第三张图片被强行换行,看起来第三张图片位置空白;尝试设置bored、margin、padding为0,并没有效果。看看HTML,看起来没什么问题

解决办法:将<img>标签间的回车去掉,写成一行;或者将图片设置为左浮动,style="display:block; float:left"

原因<img>标签是行内元素,默认排版为 inline-block;而所有的inline-block元素之间都会有空白。

  1. 在获取css文件中设置的图片宽高时,“获取”不到值;

使用document.documentElement.style.getPropertyValue("--imageWidth");得到的值为空;

解决办法:改用getComputedStyle(document.documentElement).getPropertyValue("--imageWidth");才能拿到:root选择器中设置的值;

原因

document.documentElement.style.getPropertyValue只能获取内联式样的值;
getComputedStyle(document.documentElement).getPropertyValue获取到的始终是实际的值;

注意事项

轮播图默认大小为800*240,图片大小一致时无需修改任何css、js;使用自定义大小的图片时需要修改css文件中:root--imageWidth--imageHeight的值;

参考链接

css变量赋值和取值的四种方式 原生JS实现滑动轮播图