分析:
复制元素(可以不用js来实现)
=> 原因:就是当最后一张走完的时候会出现留白的现象
=> 为了增加体验效果 , 我们会把第一张复制一份放到最后面
=> 把最后一张复制一份放到最前面
设置焦点
=> 我们的焦点需要比我们的图片少2个
自动轮播
=> 就是需要让图片动起来
=> 需要使用到定时器
=> 需要使用反复性定时器
=> 第一次运动 : -1 * bannerBox.clientWidth
=> 第二次运动 : -2 * bannerBox.clientWidth
=> 第三次运动 : -3 * bannerBox.clientWidth
运动结束
=> 我们也写成函数的形式
=> 这个函数不是上来就调用的
=> 当到了最后一张的时候我们要让图片回到对应位置
=> 焦点也需要跟着移动
=> 图片的索引: 0 1 2 3 4 5 6
=> 焦点的索引: 0 1 2 3 4
移入移出
=> 移入: 就是停止自动轮 , 需要关闭定时器
=> 移出: 自动轮播开始工作 , 再次调用我们的自动轮播的函数
点击切换
=> 就是在点击 左右按钮的时候能切换图片
=> 我们在点击焦点的时候也能到达指定的图片
=> 实现方式
-> 第一种: 单独获取 , 单独设置
-> 第二种: 事件委托的方式
- <style>
- * {
- margin: 0;
- padding: 0;
- }
-
- ul,
- ol,
- li {
- list-style: none;
- }
-
- .banner {
- width: 600px;
- height: 400px;
- border: 3px solid #333;
- margin: 50px auto;
- position: relative;
- overflow: hidden;
- }
-
- .banner>ul {
- width: 500%;
- height: 100%;
- position: absolute;
- left: 0;
- top: 0;
- display: flex;
- }
-
- .banner>ul>li {
- flex: 1;
- font-size: 100px;
- display: flex;
- justify-content: center;
- align-items: center;
- color: #fff;
- }
-
- .banner>ol {
- width: 200px;
- height: 30px;
- background-color: rgba(0, 0, 0, .5);
- border-radius: 15px;
- position: absolute;
- left: 50%;
- bottom: 30px;
- transform: translateX(-50%);
- display: flex;
- justify-content: space-evenly;
- align-items: center;
- }
-
- .banner>ol>li {
- width: 20px;
- height: 20px;
- border-radius: 50%;
- background-color: #fff;
- 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, .3);
- position: absolute;
- top: 50%;
- transform: translateY(-50%);
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 30px;
- color: #fff;
- cursor: pointer;
- display: none;
- }
-
- .banner>div:hover {
- background-color: rgba(0, 0, 0, .5);
- }
-
- .banner>div.left {
- left: 0;
- border-radius: 0 20px 20px 0;
- }
-
- .banner>div.right {
- right: 0;
- border-radius: 20px 0 0 20px;
- }
- style>
- head>
- <div class="banner">
-
- <ul class="imgBox">
- <li style="background-color: pink;">1li>
- <li style="background-color: skyblue;">2li>
- <li style="background-color: orange;">3li>
- <li style="background-color: purple;">4li>
- <li style="background-color: yellow;">5li>
- ul>
-
- <ol class="pointBox">
-
- ol>
-
- <div class="left"><div>
- <div class="right">>div>
- div>
其中调用的运动函数在上一节
-
- // 获取元素
- const imgbox = document.querySelector('.imgBox')
- const pointBox = document.querySelector('.pointBox')
- const bannerBox = document.querySelector('.banner')
-
- // 设置一个定时器的返回值
- let time = 0
-
- // 定义一个变量表示是第几张图片
- let index = 1
-
- // 定义一个开关,方便判断定时器的开关
- let flag = true
-
- // 避免留白问题,需要把前后的图片进行复制
- // 第一张放在最后一张,最后一张放在第一张前面
- eleCopy()
- function eleCopy(){
- // 复制第一张
- let first = imgbox.firstElementChild.cloneNode(true)
- // 复制最后一张
- let last = imgbox.lastElementChild.cloneNode(true)
-
- // 把复制的第一张添加到最后
- imgbox.appendChild(first)
- // 把复制的最后一张添加到第一张
- imgbox.insertBefore(last,imgbox.firstElementChild)
-
- // 需要设置承载图片的盒子宽度
- imgbox.style.width = imgbox.children.length * 100 + '%'
- // 移动我们承载图片的盒子,我们需要注意应该是banner移动
- imgbox.style.left = -1 * bannerBox.clientWidth + 'px'
-
- }
-
- // 设置焦点
- setPoint()
- function setPoint(){
- // 获取设置焦点的数量
- // 我们多复制了两张,所以焦点的数量应该-2
- let count = imgbox.children.length - 2
- // 循环生成焦点
- for(let i = 0 ; i < count; i++){
- // 创建li
- const li = document.createElement('li')
- // 把创建的li添加到对应的父级中
- pointBox.appendChild(li)
- // 给对应的li添加类名可以用来判断当前元素是否有item
- li.classList.add('item')
- // 把i当做索引,以自定义属性的方式保存在标签上
- li.dataset.id = i
- // 给第一个添加默认的类名active
- if(i === 0) li.classList.add('active')
- }
- // 设置我们承载焦点盒子的宽度
- pointBox.style.width = count * (20 + 10) + 'px'
-
- }
-
- // 自动轮播
- autoPlay()
- function autoPlay(){
- // 轮播需要用定时器
- time = setInterval(()=>{
- // 开关开启表示可以定时器是开启的
- // 但是突然点击左右尖椒的时候,会出现抖屏的情况
- // 所以我们需要关闭,不让点击
- if(!flag) return
- // 之后关闭
- flag = false
- // 这里进行index++,进行移动
- index++
- // 这里如何运动我们可以调用move函数
- move(imgbox,{'left':-index *bannerBox.clientWidth},moveEnd)
- },2000)
- }
-
- // 运动结束
- function moveEnd(){
- // 运动完最后一张的时候,需要立即回到第一张
- if(index === imgbox.children.length - 1){
- // 定位到第一张
- index = 1
- imgbox.style.left = -index * bannerBox.clientWidth + 'px'
- }
- // 运动到第一张,需要瞬间到最后一张
- if(index === 0){
- // 定位到最后一张
- index = 5
- imgbox.style.left = -index * bannerBox.clientWidth + 'px'
- }
- // 焦点跟随
- // 需要用类名进行控制,用排他思想
- for(let i = 0;i < pointBox.children.length;i++){
- pointBox.children[i].classList.remove('active')
- }
- // 给对应的加上类名
- pointBox.children[index - 1].classList.add('active')
- // 运动结束之后,打开定时器
- flag = true
- }
-
- // 移入和移出
- overOut()
- function overOut(){
- // 鼠标移入的时候需要停止定时器
- // 否则会出现抖屏的状况
- bannerBox.addEventListener('mouseover',()=>{
- clearInterval(time)
- })
- bannerBox.addEventListener('mouseout',()=>{
- // 移出之后开启轮播
- autoPlay()
- })
- }
-
- // 点击切换
- // 因为左右尖椒号、小圆点都需要点击,所以我们需要用事件委托
- clickChange()
- function clickChange(){
- bannerBox.addEventListener('click',e=>{
- // 需要找到目标元素
- let target = e.target
- // 判断你点击的元素
- if(target.className === 'left'){
- // 开关开启表示可以定时器是开启的
- // 但是突然点击左右尖椒的时候,会出现抖屏的情况,所以我们需要关闭
- if(!flag) return
- // 之后关闭
- flag = false
- // 需要进行--
- index--
- move(imgbox, {left:-index * bannerBox.clientWidth},moveEnd)
- }
- if(target.className === 'right'){
- // 开关开启表示可以定时器是开启的
- // 但是突然点击左右尖椒的时候,会出现抖屏的情况,所以我们需要关闭
- if(!flag) return
- // 之后关闭
- flag = false
- index++
- move(imgbox, {left:-index * bannerBox.clientWidth},moveEnd)
- }
- // 点击焦点
- if(target.className === 'item'){
- if(!flag) return
- // 之后关闭
- flag = false
- // 我们需要把点击的焦点对应到相对应的图片
- // 可以获取到对应的索引
- // 通过自定义属性
- index = target.dataset.id - 0 + 1
- move(imgbox, {left:-index * bannerBox.clientWidth},moveEnd)
- }
- })
- }
-
- // 当我们的页面由可见变成不可见的时候也可能会出现抖屏的情况
- // 我们也需要先把定时器关闭
- // 页面回来之后,定时器重新开始工作
- tabChange()
- function tabChange(){
- document.addEventListener('visibilitychange',()=>{
- //存在一个属性visibilityState hidden visible
- // 如果页面由可见变成了不可见,要停止定时器
- if(document.visibilityState === 'hidden'){
- clearInterval(time)
- }
- // 页面回来之后,开始自动轮播
- if(document.visibilityState === 'visible'){
- autoPlay()
- }
- })
- }
-