0%

JS 实现轮播图(附jQuery版本)

实现效果

  • 多张图片自动轮播展示,对应分页器(小圆点)高亮显示
  • 点击分页器(小圆点)切换对应图片
  • 点击前进/后退按钮切换当前图片的前一张/后一张图片
  • 图片无缝切换,第一张图片和最后一张图片无缝切换
  • 鼠标滑入停止图片切换,鼠标移出开始图片切换
  • 前进后退按钮防抖

轮播图切换

index.html(html+css)

  • 创建 index.html 文件,粘贴如下代码
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
96
97
98
99
100
101
102
<!DOCTYPE html>

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>轮播图</title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
a {
text-decoration: none;
}
#banner {
width: 1226px;
height: 460px;
margin: 100px auto;
overflow: hidden;
position: relative;
cursor: pointer;
}
#wrapper {
display: flex;
position: absolute;
left: 0;
}
#wrapper li {
width: 1226px;
height: 460px;
}
#wrapper li img {
display: block;
width: 100%;
height: 100%;
}
#list {
position: absolute;
left: 50%;
display: flex;
align-items: center;
transform: translate(-50%, -50%);
bottom: 10px;
}
#list li {
width: 10px;
height: 10px;
background: rgba(0, 0, 0, 0.4);
border: 3px solid rgba(255, 255, 255, 0.1);
border-radius: 50%;
margin: 0 5px;
}
#list li.active {
background: rgba(255, 255, 255, 0.3);
}
#left, #right {
background: url("https://i1.mifile.cn/f/i/2014/cn/icon/icon-slides.png") no-repeat;
width: 41px;
height: 69px;
position: absolute;
top: 50%;
transform: translate(0, -50%);
}
#left {
left: 0;
background-position: -84px 0;
}
#right {
right: 0;
background-position: -125px 0;
}
#left:hover {
background-position: 0 0;
}
#right:hover {
background-position: -42px 0;
}
</style>
</head>

<body>
<div id="banner">
<!-- 图片 -->
<ul id="wrapper">
<li><img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/9ebff5f5c1f52f2dbdd611897adbefd4.jpg?thumb=1&w=1226&h=460&f=webp&q=90" alt=""></li>
</ul>
<!-- 分页器(小圆点) -->
<ul id="list">
<li class="active"></li>
</ul>
<!-- 前进按钮 -->
<a href="javascript:;" id="left"></a>
<!-- 后退按钮 -->
<a href="javascript:;" id="right"></a>
</div>
<script src="index.js"></script>
</body>

</html>

不加 JS,静态界面应该是下图这样的

  • 如果图片没有请求到,可以换一个图片链接

轮播图-mi-静态界面

  • 这里需要用 Ajax 请求一下如下 json 数据
  • 创建 banner.json ,粘贴如下数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[
{
"id": 1,
"img": "https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/9ebff5f5c1f52f2dbdd611897adbefd4.jpg?thumb=1&w=1226&h=460&f=webp&q=90",
"desc": "banner1"
},
{
"id": 2,
"img": "https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/0ef4160c861b998239bce9adb82341e7.jpg?thumb=1&w=1226&h=460&f=webp&q=90",
"desc": "banner2"
},
{
"id": 3,
"img": "https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/0e4acf11840c1d9600c34c46ffa73ec8.jpg?thumb=1&w=1226&h=460&f=webp&q=90",
"desc": "banner3"
},
{
"id": 4,
"img": "https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/d65e7bc110ca74b9d7fa7ce53a841971.jpg?w=2452&h=920",
"desc": "banner4"
}
]

index.js (原生jS )

  • 原理:图片平铺在一行,然后利用定时器计算偏移量实现定时轮播
  • 切换动画效果函数可以使用正则把有效数组匹配出来 /[+-]?(0|([1-9]\d+))(\.\d+)?/g 或 把单位匹配出来 /[^+-.\d]+/g(还不太完善)
  • 注意:需要使用 live-server 启动
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// 获取页面元素
let banner = document.getElementById("banner");
let wrapper = document.getElementById("wrapper");
let list = document.getElementById("list");
let lis = list.getElementsByTagName("li");
// Ajax 请求数据
let data = null;
// 接收定时器的返回值
let timer = null;
// 当前展示图片的索引
let step = 0;

// 0.切换动画效果(简单实现jQuery animate切换效果)
function animate(ele, target, duration) {
let begin = {}
let change = {}
for (const key in target) {
begin[key] = parseFloat(window.getComputedStyle(ele)[key])
change[key] = target[key] - begin[key]
}
let time = 0
let timers = setInterval(() => {
time += 20
for (const key in target) {
ele.style[key] = time / duration * change[key] + begin[key] + "px";
}
if (time >= duration) {
clearInterval(timers);
}
}, 20)
}

// 1.数据请求 Ajax四部曲
function getData(url) {
let xhr = new XMLHttpRequest();
xhr.open("get", url, false);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
data = JSON.parse(xhr.responseText);
renderHtml(data);
}
};
xhr.send();
}
getData("./banner.json");

// 2.渲染图片
function renderHtml(data) {
let imgs = "";
let lis = "";
data.forEach((item, index) => {
imgs += `<li><img src="${item.img}" alt=""></li>`;
lis += "<li></li>";
});
// 要实现无缝滚动,需要克隆第一张图片,放到最后一张的后面
imgs += `<li><img src="${data[0].img}" alt=""></li>`;
wrapper.innerHTML = imgs;
list.innerHTML = lis;
}

// 3.实现自动轮播,每隔2000ms执行一次
function autoMove(index) {
// 图片索引自增(切换下一张图片)
step++;
// 如果当前函数执行时没有传形参index,那就什么都不做,如果形参index有值,就把index赋值给step即可
typeof index == "undefined" ? null : step = index;
// 如果当前的step>=5说明已经运动到最后一张图片了,这时候需要马上把wrapper的left值改为0
if (step >= data.length + 1) {
wrapper.style.left = 0;
// 这时step改为1,可以正常显示第二张
step = 1;
}
animate(wrapper, {
left: -1226 * step
}, 500);
changeFocus();
}
timer = setInterval(autoMove, 2000);

// 4.鼠标划上图片停止轮播 鼠标离开继续轮播
banner.onmouseover = function () {
clearInterval(timer);
}
banner.onmouseout = function () {
clearInterval(timer);
timer = setInterval(autoMove, 2000);
}

// 5.实现焦点跟随,显示哪一张图片,就给对应的焦点li加上类名active
function changeFocus() {
// 循环所有的焦点,判断一下当前的step和哪个焦点的索引相等,和谁相等就给谁加上active类名,其余的清除active类名
for (let i = 0; i < lis.length; i++) {
if (i == step) {
lis[i].classList.add("active");
} else {
lis[i].classList.remove("active");
}
}
// 如果当前的step是data.length,说明当前页面显示的是最后一张图片,它和第一张图公用一个焦点,这时让第一个焦点高亮即可
if (step == data.length) {
lis[0].classList.add("active");
}
}
changeFocus();

// 6.点击分页器(小圆点),实现切换对应图片
function bindClick() {
for (let i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
autoMove(i);
}
}
}
bindClick();

// 7.控制前进/后退按钮
right.onclick = debounce(autoMove, 300);
function lClick() {
if (step == 0) {
step = data.length;
wrapper.style.left = (data.length) * -1226 + "px";
}
step--;
autoMove(step)
}
left.onclick = debounce(lClick, 300)

// 8.防抖
function debounce(fn, wait) {
let timers = null;
let result = null;
return function (...args) {
if (timers) clearTimeout(timers);
timers = setTimeout(() => {
result = fn.apply(this, ...args);
}, wait)
return result;
}
}

jQuery版本

  • 只需替换JS部分即可
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
<script src="https://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
<script>
let timer = null;
let url = "./banner.json";
let step = 0;
let lens = 0;
// 1.数据请求
$.ajax({
url: url,
async: false,
success: (res) => {
bindHtml(res);
lens = res.length;
timer = setInterval(autoMove, 2000);
}
})
// 2.渲染图片
function bindHtml(data) {
let imgs = "";
let lis = "";
$.each(data, (index, item) => {
imgs += `<li><img src="${item.img}" alt=""></li>`;
lis += "<li></li>";
});
imgs += `<li><img src="${data[0].img}" alt=""></li>`;
$("#wrapper").html(imgs);
$("#list").html(lis);
}
// 3.实现自动轮播,每隔1000ms执行一次
function autoMove(index) {
step++;
typeof index == "undefined" ? null : step = index;
if (step >= 5) {
step = 1;
$("#wrapper").animate({
left: "0px"
}, 0)
}
$("#wrapper").animate({
left: -$("#outer").width() * step + "px",
}, 1000)
changeFocus();
}
// 4.鼠标划上图片停止轮播 鼠标离开继续轮播
$("#outer").hover(() => {
clearInterval(timer);
}, () => {
timer = setInterval(autoMove, 2000);
})
// 5.实现焦点跟随,显示哪一张图片,就给对应的焦点li加上类名active
function changeFocus() {
$("#list li").eq(step).addClass("active").siblings().removeClass("active");
if (step == lens) {
$("#list li").eq(0).addClass("active").siblings().removeClass("active");
}
}
changeFocus();
// 6.点击焦点,实现切换对应图片
function bindClick() {
$("#list li").click(function () {
autoMove($(this).index());
})
}
bindClick();
// 7.控制箭头
$("#right").click(function () {
autoMove();
})
$("#left").click(function () {
if (step == 0) {
step = lens;
$("#wrapper").animate({
left: lens * -800 + "px"
}, 0)
}
step--;
autoMove(step);
})
</script>