html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
ul, ol, li {
list-style: none;
}
.banner {
width: 600px;
height: 400px;
border: 10px solid #333;
margin: 30px auto;
position: relative;
}
.banner > ul {
width: 100%;
height: 100%;
position: relative;
}
.banner > ul > li {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
color: #fff;
font-size: 100px;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
transition: opacity .5s linear;
}
.banner > ul > li.active {
opacity: 1;
}
.banner > ol {
width: 200px;
height: 30px;
background-color: rgba(0, 0, 0, .3);
position: absolute;
left: 30px;
bottom: 30px;
border-radius: 15px;
display: flex;
/*
justify-content: 主轴对齐方式
space-between: 两端对齐
space-around: 环绕
space-evenly: 绝对均分(安卓不支持, ios 支持)
*/
justify-content: space-evenly;
align-items: center;
}
.banner > ol > li {
width: 20px;
height: 20px;
background-color: #fff;
border-radius: 50%;
cursor: pointer;
}
.banner > ol > li.active {
background-color: red;
}
.banner:hover > div {
display: flex;
}
.banner > div {
width: 30px;
height: 40px;
background-color: rgba(0, 0, 0, .2);
display: flex;
justify-content: center;
align-items: center;
color: #fff;
font-size: 20px;
position: absolute;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
display: none;
}
.banner > div:hover {
background-color: rgba(0, 0, 0, .5);
}
.banner > div.prev {
left: 0;
}
.banner > div.next {
right: 0;
}
</style>
</head>
<body>
<!-- 布局结构 -->
<div class="banner" id="banner">
<!-- 承载图片的盒子 -->
<ul class="imgBox">
<li class="active" style="background-color: pink;">1</li>
<li style="background-color: orange;">2</li>
<li style="background-color: skyblue;">3</li>
<li style="background-color: green;">4</li>
<li style="background-color: purple;">5</li>
</ul>
<!-- 承载焦点的盒子 -->
<ol class="pointBox"></ol>
<!-- 左右切换按钮 -->
<div class="prev"><</div>
<div class="next">></div>
</div>
<script src="./banner.js"></script>
<script>
const b = new Banner('#banner')
console.log(b)
</script>
</body>
</html>
js代码
class Banner {
constructor (select) {
// 范围元素
this.ele = document.querySelector(select)
// 承载图片的盒子
this.imgBox = this.ele.querySelector('.imgBox')
// 承载焦点的盒子
this.pointBox = this.ele.querySelector('.pointBox')
// 准备一个变量, 表示当前是第几张
this.index = 0
// 准备一个变量, 表示定时器
this.timerId = 0
// 调用启动器
this.init()
}
// 启动器
init () {
// 调用设置焦点的方法
this.setPoint()
// 调用自动轮播的方法
this.autoPlay()
// 调用移入移出的方法
this.overOut()
// 调用绑定事件的方法
this.bindEvent()
}
// 设置焦点
setPoint () {
// 1. 获取到需要生成多少个焦点
const pointNum = this.imgBox.children.length
// 2. 循环遍历生成焦点盒子
const frg = document.createDocumentFragment()
for (let i = 0; i < pointNum; i++) {
// 创建 li
const li = document.createElement('li')
// 给每一个 li 添加一个类名, 为了和 图片的 li 做一个区分
li.classList.add('point')
// 默认给第一个 li 添加 active 类名
if (i === 0) li.classList.add('active')
// 记录索引
li.dataset.i = i
// 把 li 放在筐里面
frg.appendChild(li)
}
// 3. 把 frg 放在 this.pointBox 内部
this.pointBox.appendChild(frg)
// 4. 选做: 调整一下焦点盒子的宽度
this.pointBox.style.width = pointNum * (20 + 10) + 'px'
}
// 切换一张
changeOne (type) {
// 1. 不管切换到哪一张, 都需要当前这一张消失
// 此时 this.index 表示的是当前这一张
// 需要让 imgBox 内部索引为 [this.index] 的那一张取消 active 类名
this.imgBox.children[this.index].classList.remove('active')
// 操作焦点
this.pointBox.children[this.index].classList.remove('active')
// 2. 通过 type 来判断, 决定 this.index 的值
switch (type) {
case true:
// 下一张
this.index++
break
case false:
// 上一张
this.index--
break
default:
// 某一张
this.index = type
}
// 3. 调整一下 this.index 的边界值
if (this.index < 0) this.index = this.imgBox.children.length - 1
if (this.index >= this.imgBox.children.length) this.index = 0
// 4. 让该显示的显示出来
// 索引为 this.index 的显示出来
this.imgBox.children[this.index].classList.add('active')
this.pointBox.children[this.index].classList.add('active')
}
// 自动轮播
autoPlay () {
// 1. 开启定时器
this.timerId = setInterval(() => {
// 2. 切换下一张
this.changeOne(true)
}, 2000)
}
// 移入移出
overOut () {
// 1. 移入事件
this.ele.addEventListener('mouseover', () => clearInterval(this.timerId))
// 2. 移出事件
this.ele.addEventListener('mouseout', () => this.autoPlay())
}
// 点击事件
bindEvent () {
// 1. 给 this.ele 绑定点击事件
this.ele.addEventListener('click', e => {
// 处理事件对象兼容
e = e || window.event
// 处理事件目标兼容
const target = e.target || e.srcElement
// 2. 判断点击的是左按钮
if (target.className === 'prev') {
// 切换上一张
this.changeOne(false)
}
// 3. 判断点击的是右按钮
if (target.className === 'next') {
// 切换下一张
this.changeOne(true)
}
// 4. 判断点击的是焦点按钮
if (target.className === 'point') {
// 需要拿到你点击的这个 li 的索引
// 提前把索引以自定义属性的形式记录下来
const i = target.dataset.i - 0
// 切换某一张
this.changeOne(i)
}
})
}
}