js源码 (html css 参考js类语法面向对象实现轮播图)
/*
轮播图js代码
*/
// 1. 获取元素
// 1-1. 获取承载图片的 imgBox
const imgBox = document.querySelector('.imgBox')
// 1-2. 可视窗口的盒子
const banner = document.querySelector('.banner')
// 1-3. 承载焦点的盒子 pointBox
const pointBox = document.querySelector('.pointBox')
// 2. 准备变量
// 2-1. 准备一个变量表示第几张
let index = 1
// 2-2. 准备一个变量记录可视窗口的宽度
// 元素.clientWidth 获取到的是元素 内容 + padding 区域的尺寸
const banner_width = banner.clientWidth
// 2-3. 准备一个变量接受定时器返回值
let timerId = 0
// 2-4. 准备一个变量表示开关
let flag = true
// 3. 代码逻辑
// 3-1. 复制元素
copyEle()
function copyEle() {
// 1. 克隆 第一个 和 最后一个 子元素
const first = imgBox.firstElementChild.cloneNode(true)
const last = imgBox.lastElementChild.cloneNode(true)
// 2. 插入元素
// 把第一个插入到最后
imgBox.appendChild(first)
// 把最后一个插入到最前
imgBox.insertBefore(last, imgBox.firstElementChild)
// 3. 调整 imgBox 的宽度
imgBox.style.width = imgBox.children.length * 100 + '%'
// 4. 调整 imgBox 的 left 的值
imgBox.style.left = -index * banner_width + 'px'
}
// 3-2. 设置焦点
setPoint()
function setPoint() {
// 1. 拿到需要生成多少个焦点按钮的数量
const pointNum = imgBox.children.length - 2
// 2. 准备一个筐
const frg = document.createDocumentFragment()
// 3. 循环遍历生成 焦点li 放在 frg 内部
for (let i = 0; i < pointNum; i++) {
// 生成 li
const li = document.createElement('li')
// 要默认给第一个加上 active 类名
if (i === 0) li.classList.add('active')
// 给每一个 li 添加一个 point 的类名
li.classList.add('point')
// 给每一个 li 添加一个 自定义属性
li.dataset.pointIndex = i
// 放在筐里面
frg.appendChild(li)
}
// 4. 把 frg 放在 pointBox 内部
pointBox.appendChild(frg)
// 5. 调整一下 pointBox 的宽度
pointBox.style.width = pointNum * (20 + 10) + 'px'
}
// 3-3. 自动轮播
autoPlay()
function autoPlay() {
// 1. 开启定时器
timerId = setInterval(() => {
// 2. 调整 index
index++
// 3. 让 imgBox 运动到第 index 张的位置
// 调用 move 函数让 imgBox 运动
move(imgBox, {
left: -index * banner_width
}, moveEnd)
}, 2000)
}
// 3-4. 运动结束
function moveEnd() {
// 1. 向前进行瞬间定位
// 我怎么知道来到真的最后一张了
// 有 x 张图片, 最后一张的索引是 x-1
if (index === imgBox.children.length - 1) {
// 瞬间定位到真的第一张
index = 1
// 不需要运动, 需要瞬间定位
imgBox.style.left = -index * banner_width + 'px'
}
// 2. 向后进行瞬间定位
// 你怎么知道来到的假的最后一张
if (index === 0) {
// 瞬间定位到真的最后一张
// 真的最后一张索引 length - 2
index = imgBox.children.length - 2
// 不需要运动函数, 瞬间进行定位
imgBox.style.left = -index * banner_width + 'px'
}
// 3. 焦点配套
// 给所有焦点去掉类名
for (let i = 0; i < pointBox.children.length; i++) {
pointBox.children[i].classList.remove('active')
}
// 给指定的那一个添加 active 类名
// 指定: index - 1
pointBox.children[index - 1].classList.add('active')
// 8-3. 再次开启开关
// 代码执行到这里, 表示一张图片切换完毕了
// 该瞬间定位的已经调整完毕了
// 该切换的焦点也切换完毕了
// 可以正常去切换下一张了
flag = true
}
// 3-5. 移入移出
overOut()
function overOut() {
// 1. 移入停止自动轮播
banner.addEventListener('mouseover', () => clearInterval(timerId))
// 2. 移出再次开启自动轮播
banner.addEventListener('mouseout', () => autoPlay())
}
// 3-6. 绑定事件
bindEvent()
function bindEvent() {
// 1. 给 banner 盒子绑定点击事件
banner.addEventListener('click', e => {
// 处理事件对象兼容
e = e || window.event
// 处理事件目标兼容
// 事件目标: 准确触发事件的那个元素
const target = e.target || e.srcElement
// 2. 判断你准确的点击的是哪一个元素
// 2-1. 判断左按钮
if (target.className === 'prevBtn') {
if (flag === false) return
flag = false
// 操作 index
index--
// 使用 move 函数
move(imgBox, {
left: -index * banner_width
}, moveEnd)
}
// 2-2. 判断右按钮
if (target.className === 'nextBtn') {
// 8-1. 判断开关如果是关闭的, 那么什么都不做了
if (flag === false) return
// 8-2. 关闭开关
// 代码能执行到这里, 表示开关是开启状态
// 把开关关闭
flag = false
// 操作 index
index++
// 使用 move 函数
move(imgBox, {
left: -index * banner_width
}, moveEnd)
}
// 2-3. 判断焦点按钮
if (target.className === 'point') {
if (flag === false) return
flag = false
// 给 index 赋值为焦点的 索引 + 1
index = target.dataset.pointIndex - 0 + 1
// 使用 move 函数
move(imgBox, {
left: -index * banner_width
}, moveEnd)
}
})
}
// 3-7. 解决离开页面抖动
changeTab()
function changeTab() {
// 1. 给 document 绑定一个 visibilitychange 事件
document.addEventListener('visibilitychange', () => {
// 2. 通过可视程度决定如何操作
if (document.visibilityState === 'hidden') clearInterval(timerId)
if (document.visibilityState === 'visible') autoPlay()
})
}