左右切换轮播图-swiper插件-面向对象

本文详细介绍了如何使用面向对象的方法实现一个左右切换的轮播图,包括获取元素、复制元素、自动轮播、移入移出、焦点切换等功能。通过设置开关避免在动画过程中触发不必要的操作,解决鬼畜问题,并处理页面切换时的定时器管理,确保轮播图的平滑运行和用户体验。
摘要由CSDN通过智能技术生成

轮播图的代码
一个小小的建议

  1. 先要看得懂 -> 表示你听懂了 -> 如果看不懂, 那么直接问老师
  2. 自己写注释 -> 留着上课的代码, 自己写注释 -> 表示你理解了
  3. 看着自己的注释写代码 -> 某些方法不会, 自己去翻翻笔记 -> 表示你学会了
  4. 如果你能自己先写一个思路, 按照思路写代码 -> 表示你记住了
    思路
  5. 获取元素
    => div.banner 需要的, 我们需要他的宽度
    -> 因为 ul 一次运动就应该运动一个可视窗口的宽度
    -> 因为每一张图片都和可视窗口一边宽
    -> 一次运动一张图片, 就是运动一个可视窗口的宽度
    => ul.imgBox 需要的, 因为每次运动都是让这个 ul 在运动
    -> 因为这个 ul 里面承载着若干个 li
    -> ul 运动, 就会带着里面的所有 li 一起运动
    => ol.pointBox 需要的, 因为需要控制每一个 li 的类名
    -> 每次运动结束以后, 我们需要控制 li 的类名切换
    -> 每一个焦点按钮也需要一个点击事件
    => p.prev 需要的, 因为要有上一张的点击事件
    => p.next 需要的, 因为要有下一张的点击事件
  6. ol.pointBox 里面的 li 是动态创建还是直接写好
    => 如果直接写好, 那么我每加减一个图片, 也要对应的去操作
    => 也可以根据 ul.imgBox 盒子里面图片的数量来生成
    => 如果是生成的, 那么我每次加减图片的时候, 就不需要操心这个焦点了
    => 我们要根据 ul.imgBox 里面子元素的数量来创建对应的 li 添加到 ol.pointBox 里面
  7. 复制元素
    => 要把 ul.imgBox 里面本身的第一张复制一个
    => 要把 ul.imgBox 里面本身的最后一张复制一个
    => 复制的第一张放在最后, 复制的最后一张放在最前面
  8. 自动轮播
    => 每间隔一段时间, 让 ul.imgBox 向负方向移动一个可视窗口的距离
    => 每间隔一段时间, setInterval()
    => 让某一个元素移动一段距离, move() 函数
    => 我要知道你移动到第几张
    => 最开始准备一个变量记录是第几张
  9. 运动结束的时候拉回来
    => 需要在 move 函数的第三个参数, 也就是运动结束的时候做点事情
    => 当他走到最后一张的时候, 把他瞬间定位回到索引 [1] 的那一张
    => 运动结束的时候, 让焦点也改变一下
    => 和图片配套的焦点按钮有 active 类名, 让其余的所有焦点都没有类名
  10. 移入移出
    => 移入 banner 盒子的时候, 停止自动轮播, 清除定时器
    => 移出 banner 盒子的时候, 重新开启定时器, 继续自动轮播
    => 因为移入你有可能点击各种按钮(左右, 焦点)
  11. 左右切换
    => 点击 p.next 就是看到下一张
    => 点击 p.prev 就是看到上一张
    => 下一张就是 index++
    => 上一张就是 index–
    => 都是依靠 move 函数来运动到上一张或者下一张
  12. 焦点切换
    => 每一个焦点按钮都有一个点击事件
    => 点击每一个焦点按钮的时候都能触发点事情
    => 你点击的是哪一个按钮, 就应该切换到对应的那一张图片上
  13. 解决鬼畜
    => 因为你每次点击(左右按钮, 焦点), 都会让轮播图切换
    => 当他没有切换完毕的时候, 你马上又进行了下一次点击
    => 他就会乱了, 因为他需要在运动结束以后, 判断 index 的值
    => 来决定是不是要拉回来, 你在他没有运动完毕, 就一直点击
    => index 一定会超过边界值
    => 解决问题:
    -> 我们设置一个开关
    -> 当他正在运动的时候, 我们把开关关闭
    -> 我们的所有点击事件里面都进行判断
    -> 只要开关是开着的, 那么我就执行点击的行为
    -> 如果开关时关着的, 那么我就不执行点击的行为
  14. 切换标签页
    => 因为当你切换标签页, 或者最小化的时候
    => 我们叫做离开当前页面
    => 浏览器一旦离开当前页面, 那么 DOM 操作是会停止的
    -> 但是定时器不会停
    => 就造成了一个问题, 定时器继续走着, 积攒了很多的 DOM 操作没有执行
    => 等到你切换回来的时候, 一次性把所有积攒的 DOM 操作全部执行了
    => 就会出现鬼畜现象
    => 解决问题:
    -> 只要我能捕获到我离开当前页面的行为
    -> 那么我就可以在离开页面的时候关闭定时器
    -> 回到页面的时候再次执行自动轮播
    => 有一个事件叫做 visibilitychange 事件
    -> 只能绑定在 document 上
    -> 当前页面显示或者隐藏的时候就会触发
    -> 离开页面会触发, 回到页面也会触发
    => 在 document 身上有一个属性叫做 visibilityState
    -> 他的值决定了页面时显示还是隐藏
    -> hidden 表示离开当前页面
    -> visible 表示回到当前页面
    // 1-1. 获取元素
    // 最外层盒子
    let bannerBox = document.querySelector(’.banner’)
    // ul.imgBox 承载图片的盒子
    let imgBox = document.querySelector(’.imgBox’)
    // ol.pointBox 承载焦点按钮的盒子
    let pointBox = document.querySelector(’.pointBox’)
    // p.prev 上一张按钮
    let prevBtn = document.querySelector(’.prev’)
    // p.next 下一张按钮
    let nextBtn = document.querySelector(’.next’)
    // 1-2. 准备一些变量
    // 准备一个 bannerBox 的宽度
    let bannerWidth = bannerBox.clientWidth
    // 准备一个记录索引的变量, 默认是 1
    let index = 1
    // 准备一个记录定时器返回值的变量
    let timerId = 0
    // 准备一个变量当作开关
    let flag = true
    // 2. 设置焦点
    setPoint()
    // 3. 复制元素
    copyEle()
    // 4. 自动轮播
    autoPlay()
    // 6. 移入移出
    overOut()
    // 7. 左右切换
    leftRight()
    // 8. 焦点切换
    pointChange()
    // 10. 切换页面
    pageChange()
    // 设置焦点的函数
    function setPoint() {
    // 2-1. 获取 imgBox 里面又多少个子元素
    let pointNum = imgBox.children.length
    // 2-2. 准备一个文档碎片, 用来承载焦点
    let frg = document.createDocumentFragment()
    // 2-3. 循环
    for (let i = 0; i < pointNum; i++) {
    // 2-4. 创建 li
    let li = document.createElement(‘li’)
    // 2-5. 第一个 li 默认有一个 active 类名
    if (i === 0) li.className = ‘active’
    // 2-6. 把创建好的 li 放在文档碎片里面
    frg.appendChild(li)
    }
    // 2-7. 把文档碎片直接添加到 pointBox 里面
    pointBox.appendChild(frg)
    // 2-8. 重新设置一下 pointBox 的宽度, 避免焦点多了以后太拥挤
    pointBox.style.width = pointNum * 20 * 1.5 + ‘px’
    }
    // 赋值元素的函数
    function copyEle() {
    // 3-1. 复制一个本身的第一张
    let first = imgBox.firstElementChild.cloneNode(true)
    // 3-2. 复制一个本身的最后一张
    let last = imgBox.lastElementChild.cloneNode(true)
    // 3-3. 把本身的第一张放在最后
    imgBox.appendChild(first)
    // 3-4. 把本身的最后一张放在最前面
    imgBox.insertBefore(last, imgBox.firstElementChild)
    // 3-5. 重新设置 imgBox 的宽度
    imgBox.style.width = imgBox.children.length * 100 + ‘%’
    // 3-6. 定位元素, 定位到第一张的位置
    imgBox.style.left = -bannerWidth + ‘px’
    }
    // 自动轮播的函数
    function autoPlay() {
    // 4-1. 开启一个定时器, 每间隔一段时间换到下一张
    timerId = setInterval(() => {
    // 4-2. 准备的索引变量++
    index++
    // 4-3. 通过调用 move 函数让 imgBox 移动
    move(imgBox, { left: -index * bannerWidth }, moveEnd)
    }, 1000)
    }
    // 运动结束的函数
    function moveEnd() {
    // 这个函数会在一张图片运动结束后触发
    // 这一张图片没有运动结束的时候, 不会触发这个函数
    // 5-1. 判断运动到最后一张了, 我们把他瞬间定位到第一张
    if (index === imgBox.children.length - 1) {
    index = 1
    imgBox.style.left = -index * bannerWidth + ‘px’
    }
    // 5-2. 判断当运动到索引为 0 的那一张, 瞬间定位到到数第二章
    if (index === 0) {
    index = imgBox.children.length - 2
    imgBox.style.left = -index * bannerWidth + ‘px’
    }
    // 5-3. 让其余的所有焦点都没有类名
    for (let i = 0; i < pointBox.children.length; i++) {
    pointBox.children[i].className = ‘’
    }
    // 5-4. 让 index 对应的那一个焦点又类名
    pointBox.children[index - 1].className = ‘active’

// 5-1 和 5-2 时判断要不要定位 imgBox
// 5-3 和 5-4 是在切换焦点按钮的类名
// 以上四个步骤都完毕以后, 表示一张图片运动结束了
// 该判断的也判断了, 该切换的也切换了
// 可以正常去切换下一张了
// 此时打开开关
// 9-2. 再次打开开关
flag = true
}
// 移入移出的函数
function overOut() {
// 6-1. 移入 banner 盒子的时候, 停止定时器
bannerBox.addEventListener(‘mouseover’, () => clearInterval(timerId))

// 6-2. 移出 banner 盒子的时候, 继续轮播
bannerBox.addEventListener(‘mouseout’, () => autoPlay())
}
// 左右切换的函数
function leftRight() {
// 7-1. 给上一张和下一张按钮绑定点击事件
prevBtn.addEventListener(‘click’, () => {
// 9-1. 判断开关来决定是不是执行切换上一张的行为
if (flag === false) return
flag = false
// 7-2. 操作上一张
index–
// 7-3. 通过调用运动函数让 imgBox 运动到上一张
move(imgBox, { left: -index * bannerWidth }, moveEnd)
})
nextBtn.addEventListener(‘click’, () => {
// 9-1. 判断, 如果开关是关着的, 那么我直接 return
if (flag === false) return
flag = false
// 7-2. 操作下一张
index++
// 7-3. 通过调用运动函数让 imgBox 运动到下一张
move(imgBox, { left: -index * bannerWidth }, moveEnd)
})
}
// 焦点切换的函数
function pointChange() {
// 8-1. 循环遍历每一个焦点按钮
for (let i = 0; i < pointBox.children.length; i++) {
// 8-2. 给每一个焦点按钮绑定点击事件
pointBox.children[i].addEventListener(‘click’, () => {
// 9-1. 通过判断开关来决定要不要执行切换到指定某一张的操作
if (flag === false) return
flag = false
// 8-3. 让 index 设置为焦点对应的那个数字
index = i + 1
// 8-4. 通过调用运动函数, 让 imgBox 运动到指定位置
move(imgBox, { left: -index * bannerWidth }, moveEnd)
})
}
}
// 切换页面的函数
function pageChange() {
// 10-1. 给 document 绑定一个 visibilitychange 事件
document.addEventListener(‘visibilitychange’, () => {
// 10-2. 通过判断 visibilityState 属性, 来决定时什么状态
// 一定要写 else if , 因为 visibilityState 属性一共有四种值
if (document.visibilityState === ‘hidden’) {
// 表示离开当前页面了
// 关闭定时器
clearInterval(timerId)
} else if (document.visibilityState === ‘visible’) {
// 表示回到当前页面了
// 开启自动轮播
autoPlay()
}
})
}
轮播图的代码
思路

  1. 获取元素
    => div.banner 需要的, 我们需要他的宽度
    -> 因为 ul 一次运动就应该运动一个可视窗口的宽度
    -> 因为每一张图片都和可视窗口一边宽
    -> 一次运动一张图片, 就是运动一个可视窗口的宽度
    => ul.imgBox 需要的, 因为每次运动都是让这个 ul 在运动
    -> 因为这个 ul 里面承载着若干个 li
    -> ul 运动, 就会带着里面的所有 li 一起运动
    => ol.pointBox 需要的, 因为需要控制每一个 li 的类名
    -> 每次运动结束以后, 我们需要控制 li 的类名切换
    -> 每一个焦点按钮也需要一个点击事件
    => p.prev 需要的, 因为要有上一张的点击事件
    => p.next 需要的, 因为要有下一张的点击事件
  2. ol.pointBox 里面的 li 是动态创建还是直接写好
    => 如果直接写好, 那么我每加减一个图片, 也要对应的去操作
    => 也可以根据 ul.imgBox 盒子里面图片的数量来生成
    => 如果是生成的, 那么我每次加减图片的时候, 就不需要操心这个焦点了
    => 我们要根据 ul.imgBox 里面子元素的数量来创建对应的 li 添加到 ol.pointBox 里面
    // 1. 获取元素
    // 最外层盒子
    let bannerBox = document.querySelector(’.banner’)
    // 承载图片的 ul 盒子
    let imgBox = document.querySelector(’.imgBox’)
    // 承载焦点的 ol 盒子
    let pointBox = document.querySelector(’.pointBox’)
    // 上一张按钮
    let prevBtn = document.querySelector(’.prev’)
    // 下一张按钮
    let nextBtn = document.querySelector(’.next’)
    // 2. 根据图片数量创建焦点
    setPoint()
    轮播图的代码
    思路
  3. 获取元素
    => div.banner 需要的, 我们需要他的宽度
    -> 因为 ul 一次运动就应该运动一个可视窗口的宽度
    -> 因为每一张图片都和可视窗口一边宽
    -> 一次运动一张图片, 就是运动一个可视窗口的宽度
    => ul.imgBox 需要的, 因为每次运动都是让这个 ul 在运动
    -> 因为这个 ul 里面承载着若干个 li
    -> ul 运动, 就会带着里面的所有 li 一起运动
    => ol.pointBox 需要的, 因为需要控制每一个 li 的类名
    -> 每次运动结束以后, 我们需要控制 li 的类名切换
    -> 每一个焦点按钮也需要一个点击事件
    => p.prev 需要的, 因为要有上一张的点击事件
    => p.next 需要的, 因为要有下一张的点击事件
  4. ol.pointBox 里面的 li 是动态创建还是直接写好
    => 如果直接写好, 那么我每加减一个图片, 也要对应的去操作
    => 也可以根据 ul.imgBox 盒子里面图片的数量来生成
    => 如果是生成的, 那么我每次加减图片的时候, 就不需要操心这个焦点了
    => 我们要根据 ul.imgBox 里面子元素的数量来创建对应的 li 添加到 ol.pointBox 里面
  5. 复制元素
    => 要把 ul.imgBox 里面本身的第一张复制一个
    => 要把 ul.imgBox 里面本身的最后一张复制一个
    => 复制的第一张放在最后, 复制的最后一张放在最前面
    // 1-1. 获取元素
    // 最外层盒子
    let bannerBox = document.querySelector(’.banner’)
    // 承载图片的 ul 盒子
    let imgBox = document.querySelector(’.imgBox’)
    // 承载焦点的 ol 盒子
    let pointBox = document.querySelector(’.pointBox’)
    // 上一张按钮
    let prevBtn = document.querySelector(’.prev’)
    // 下一张按钮
    let nextBtn = document.querySelector(’.next’)
    // 1-2. 准备一些变量
    // 获取到最外层盒子的宽度
    let bannerWidth = bannerBox.clientWidth
    // 2. 根据图片数量创建焦点
    setPoint()
    // 3. 复制 imgBox 里面的第一个和最后一个元素
    copyEle()
    // 创建焦点的方法
    function setPoint() {
    // 2-1. 获取到 ul.imgBox 这个元素下有多少个子元素
    let pointNum = imgBox.children.length
    // 2-2. 准备一个文档碎片(筐, DAY11 讲的)
    let frg = document.createDocumentFragment()
    // 2-3. 循环创建焦点 li
    for (let i = 0; i < pointNum; i++) {
    // 2-4. 随着循环创建 li
    let li = document.createElement(‘li’)
    // 2-5. 如果是第一个 li 要有一个 active 类名
    if (i === 0) li.className = ‘active’
    // 2-6. 把创建好的 li 放到筐里
    frg.appendChild(li)
    }
    // 2-7. 都准备好了以后, 把筐里的内容添加到 ol.pointBox 里面
    pointBox.appendChild(frg)
    // 2-8. 重新根据焦点的个数设置一下 ol.pointBox 盒子的宽度
    pointBox.style.width = pointNum * 20 * 1.5 + ‘px’
    }
    // 复制元素的方法
    function copyEle() {
    // 把 ul.imgBox 里面的第一张和最后一张复制一份
    // 3-1. 复制第一个 li
    // 复制的时候传递一个 tru
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值