用JavaScript封装轮播图函数
一. 函数特点
可根据项目需求,自动选择是否自动播放,是否需要左右切换按钮,以及是否需要底部滑块按钮。
二. 函数形参含义
2.1 imgBox:
图片容器,包含所有需要展示图片的盒子(图片浮动排版在该盒子内),需要获取imgBox标签元素,方便复制图片并添加到imgBox里面
2.2 travelDistance:
轮播图滚动一次移动的距离,(imgBoxParent盒子的宽度或者每张图片的宽度)
2.3 imgBoxParent:
imgBox的父盒子,当鼠标放入轮播图时(图片、左右按钮及底部滑块)需要立即停止定时器,不直接用imgBox的原因在于,如果鼠标放在左右按钮和滑块按钮区域时,定时器不会停止,需要获取imgBoxParent标签元素
2.4 timerCode:
是否开启定时器,传入布尔值true or false
2.5 arrows:
是否需要左右切换按钮,若需要则获取arrows的子元素的HTMLCollection元素集合,若不需要则不用传该参数
2.6 slider:
是否需要底部滑块按钮,若需要则获取滑块的的父标签元素slider为参数传入,方便动态创建和添加滑块子元素,若不需要则不用传该参数
2.7 currentActiveColor:
底部滑块按钮处于活跃时所具有的class类名,传入该参数的类型须为String
三. 函数内容
el.style.left获取的值为字符串且带px,所以用el.style.left给目标盒子赋值,用el.offsetLeft来获取目标盒子距离左侧的距离
// banner.js
function slideShow(imgBox, travelDistance, imgBoxParent, timerCode, arrows, slider, currentActiveColor) {
// 2.实现无缝轮播的重要条件
// 复制imgBox盒子里的第一张图片及内容
let newItemImgBox = imgBox.children[0].cloneNode(true);
// 并添加到imgBox盒子的尾部以达到无缝轮播的效果
imgBox.appendChild(newItemImgBox);
// 3.动态创建滑块按钮,并添加到slider标签元素里面,点亮第一个滑块按钮
if (slider) {
// 根据图片的个数创建底部滑块的个数,由于复制了一张图片(该图片只用于无缝衔接),所以需要-1
for (let i = 0; i < imgBox.children.length - 1; i++) {
// 创建滑块按钮标签
let newItemslider = document.createElement('span');
// 将滑块按钮标签添加到slider标签内
slider.appendChild(newItemslider);
}
// 将第一个滑块置为活跃状态
slider.children[0].className = currentActiveColor;
// 鼠标放入滑块时切换显示对应的图片
for (let j = 0; j < slider.children.length; j++) {
// 用闭包解决由于是异步操作而无法获取元素对应下标的问题
slider.children[j].onmouseover = function (el) {
return function () {
// 将所有滑块的类名清空
for (let k = 0; k < slider.children.length; k++) {
slider.children[k].className = '';
}
// 为鼠标所在的当前滑块添加活跃类名
this.className = currentActiveColor;
// 根据鼠标所在的位置,同步移动盒子imgBox的位置,以显示对应的图片
animate(imgBox, - el * travelDistance)
// 将该下标值同步到currentImgIndex(记录当前显示图片的下标的变量)以及currentSliderIndex(记录当前活跃滑块的下标的变量)
currentImgIndex = currentSliderIndex = el;
}
}(j);
}
}
// 4.是否添加定时器函数部分(默认从左向右切换图片,也就是imgBox向左移动)
if (timerCode) {
// 由于let具有块作用域的特性,这里需要使用val,方便其他地方拿取
var isTimer = setInterval(autoplay, 3000);
// 记录图片是为了让imgBox根据当前显示的图片,移动相应的距离,记录滑块是为了让当前显示的图片,对应的滑块处于活跃状态
var currentImgIndex = 0; // 记录当前显示图片的下标
var currentSliderIndex = 0; // 记录当前活跃滑块的下标
function autoplay() {
// 图片部分
// 每向左移动一次,下标+1,也就是若现在显示的图片为第二张,而该图片的下标是1,currentImgIndex初始值为0,所以需要+1来保持一一对应
currentImgIndex++;
// 当滑到最后一张图片的时候(注意最后一张图片和第一张是一样的)
if (currentImgIndex > imgBox.children.length - 1) {
// 此时需要移动imgBox位置,让现在显示的是第一张图片,所以imgBox距离imgBoxParent的左边距为0
imgBox.style.left = 0;
// 此刻正在显示的是第一张图片,接下来就该第二张了,所以需要将currentImgIndex赋值为1
currentImgIndex = 1;
}
// 调用函数,根据当前显示图片的下标,来让盒子移动相应的位置,否则不管怎么点图片都是不动的
animate(imgBox, -currentImgIndex * travelDistance);
// 底部滑块部分
if (slider) {
// 每切换一次,下标+1,底部滑块和图片是一一对应的,需要注意的是他们所在的集合长度不一样,因为图片多复制了一张
currentSliderIndex++;
// 当前滑块的下标值大于最后一个滑块的下标值时,说明此时到第一张图片了,需要显示第一个滑块,所以currentSliderIndex置为0
if (currentSliderIndex > slider.children.length - 1) {
currentSliderIndex = 0;
}
// 然后清空所有滑块的类名
for (let i = 0; i < slider.children.length; i++) {
slider.children[i].className = '';
}
// 给当前的滑块加上活跃类名
slider.children[currentSliderIndex].className = currentActiveColor;
}
}
}
// 4.1当鼠标位于imgBoxParent上方时,清除定时器,移开后再开启定时器
if (imgBoxParent) {
imgBoxParent.onmouseover = function () {
clearInterval(isTimer);
}
imgBoxParent.onmouseout = function () {
isTimer = setInterval(autoplay, 3000);
}
}
// 5.左右箭头切换图片部分
// 5.1 左侧箭头部分
if (arrows) {
arrows[0].onclick = function () {
// 点击左侧按钮时,记录下标值的变量-1
currentImgIndex--;
// 当下标值小于0时,说明现在应该显示倒数第二张图片(因为最后一张图片和第一张图片是一样的)
if (currentImgIndex < 0) {
// 所以将imgBox距离imgBoxParent左边的距离置为倒数第二张图片距离imgBox左边的距离
imgBox.style.left = - travelDistance * (imgBox.children.length - 1) + 'px';
// 并且当前倒数第二张图片的下标值赋给currentImgIndex
currentImgIndex = (imgBox.children.length - 1) - 1;
}
// 调用函数,将盒子imgBox移动到相应的位置
animate(imgBox, -currentImgIndex * travelDistance)
// 下面滑块跟着移动部分(如果没传滑块参数,则不执行下面代码)
if (!slider) return
// 点击左侧按钮时,记录滑块的下标跟着变化,每次-1
currentSliderIndex--;
// 当下标值小于0时,说明现在应该显示倒数第二张图片(因为最后一张图片和第一张图片是一样的)
if (currentSliderIndex < 0) {
// 倒数第二张图片对应的是最后一个滑块,所以将最后一个滑块的下标值赋给currentSliderIndex
currentSliderIndex = slider.children.length - 1;
}
// 循环清空所有滑块的样式
for (let i = 0; i < slider.children.length; i++) {
slider.children[i].className = '';
}
// 给当前图片对应的滑块添加上活跃样式
slider.children[currentSliderIndex].className = currentActiveColor;
}
// 右侧箭头部分,和定时器运动方向一样(从左到右播放),点击右侧按钮时直接调用函数
arrows[1].onclick = function () {
autoplay();
}
}
// 1.盒子从当前值移动到目标值时调用的函数
function animate(el, target) {
// 多次点击时,会造成el对应的盒子运动的越来越快,所以需要防抖处理,每次进入函数前先清除它的定时器
clearInterval(el.Timer);
// 对比目标位置与盒子当前位置的大小,来决定速度的正反
let speed = target > el.offsetLeft ? 100 : -100;
// 为需要移动的盒子el添加定时器
el.Timer = setInterval(function () {
// 获取每次移动后距离目标位置剩余的距离
let value = target - el.offsetLeft;
// 且把移动的距离赋值给盒子,以达到盒子目前的位置就是其真实的位置
el.style.left = el.offsetLeft + speed + 'px';
// 判断距离目标剩余的位置是否够一次步长(一次移动的距离)
if (Math.abs(value) < Math.abs(speed)) {
// 如果不够,就直接将目标距离的位置赋值给盒子,并且清除定时器
el.style.left = target + 'px';
// 否则永远到不了目标位置
clearInterval(el.Timer);
}
}, 50)
}
}
四. 实例部分
4.1 代码部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 装轮播图片、左右切换按钮以及底部滑块的盒子,也就是方法里面说的imgBoxParent */
.slide-show-box {
width: 1200px;
height: 520px;
margin: 20px auto;
overflow: hidden;
position: relative;
}
/* 装轮播图片的盒子 */
.slide-show-box .imgbox {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 4800px;
height: 520px;
}
/* 轮播图片 */
.slide-show-box .imgbox img {
width: 1200px;
height: 520px;
float: left;
}
/* 向左切换按钮 */
.slide-show-box .arrows-l {
cursor: pointer;
position: absolute;
left: 30px;
top: 224px;
}
/* 向右切换按钮 */
.slide-show-box .arrows-r {
cursor: pointer;
position: absolute;
right: 30px;
top: 224px;
}
/* 底部滑块父盒子元素 */
.slide-show-box .slider {
height: 20px;
position: absolute;
bottom: 10px;
left: 500px;
}
/* 底部滑块子元素 */
.slide-show-box .slider span {
float: left;
display: block;
width: 40px;
height: 10px;
margin-right: 20px;
border-radius: 5px;
background-color: #84a7af;
cursor: pointer;
}
/* 当前活跃滑块的样式 */
.slide-show-box .slider .activeColor {
background-color: #ffc0cb;
}
</style>
</head>
<body>
<div class="slide-show">
<div class="slide-show-box">
<div class="imgbox">
<img src="./images/slide_show_one.jpg" alt="">
<img src="./images/slide_show_two.png" alt="">
<img src="./images/slide_show_three.jpg" alt="">
</div>
<div class="arrows">
<div class="arrows-l">
<img src="./images/arrows_l.png" alt="">
</div>
<div class="arrows-r">
<img src="./images/arrows_r.png" alt="">
</div>
</div>
<div class="slider">
</div>
</div>
</div>
<script src="./banner.js"></script>
<script>
let imgBox = document.querySelector('.imgbox')
let travelDistance = 1200 // 我的图片是1200宽
let imgBoxParent = document.querySelector(".slide-show-box")
let timerCode = true
let arrows = document.querySelectorAll('.arrows')[0].children
let slider = document.querySelector('.slider')
let currentActiveColor = 'activeColor'
// 调用封装的轮播图函数
slideShow(imgBox, travelDistance, imgBoxParent, timerCode, arrows, slider, currentActiveColor)
</script>
</body>
</html>
4.2 效果图
五. 总结
以上即可实现效果,复制代码更改图片即可直接使用。