dom&Bom_05Day


mix

1-location.href=’./xxx.html’可以跳转页面。

2-window.confirm(‘’)和alert(‘’)差不多

3-固定定位和绝对定位和浮动都脱标,块元素会变成行内块元素。

3-固定定位的left/top/bottom/right等是基于浏览器窗口定位的,相对定位是基于自己,绝对定位是相对于父级。

4-transform:translateY/X(50%)是基于自己本身的大小

5-当可视窗口大小发生变化的事件,resize

6-如ul中多个li,给所有li绝对定位absolute后,会重叠到一起(可以通过给上面内容设置opacity看到下面的内容),因为没设置left和top的话,默认定在父级左上角。

7-虽然浮动脱标,不能给父级元素撑起高度,然后标准流的盒子会去占浮动盒子的位置,但是当标准流盒子有内容,是无法互相层叠的,如浮动的最初设计是用于设置文字环绕图片的效果,图片浮动,但是文字是标准流,它们是不重叠的。

参考:https://blog.csdn.net/codeHeYiQing/article/details/105179576

8-类名和变量都是区分大小写的。

JS特效

现在来说,最好建议用css来写特效和动画,js多用于来触发它,js和css搭配使用才会最方便最简洁,效果最好。

滚动和加载事件

716

其中window也可以换成任意一个有滚动条的元素对象。如一个div内容超出盒子,overflow:auto后有滚动条也可用此事件监听。

加载事件

717

这里是load事件,给window加则是等整个window,包括图片,外联css和js等都加载完毕,再执行事件函数。

作用:有时页面资源没加载完,我们是做不了事情的,比如一个图片都没加载出来,你没办法去操作它;其次是老代码js写在body前面,body中的dom树结构节点都没有,怎么可能被js操作。

拓展:上面是给window添加load事件,等window加载完就执行;当然也可以给其他对象添加,如一个图片img.addEventListener(‘load’,function(){}),就是等这个图片加载完再执行。

DOMContentLoaded

718

DOMContentLoaded和load的区别就是,前者是 使用的对象中的dom树节点加载完毕即可,如div这些标签加载完就行了;后者是外联css/js/图片等都加载完才可以。

注意事件大小写,写错就不生效的,一般是小驼峰,这个事件DOM全大写了

元素大小和位置

scroll

作用:获取用户滚动了多少像素,从而精准进行交互。

719

720

其中scrollWidth和scrollHeight是获取盒子对象内容的大小的,而非盒子大小

721

如上盒子是150x150,但是scrollHeight是336,因为内容超出了。

当内容没超出,如就一行字,内容就是150x150大小,不是说内容就是div里面的文字等,盒子本身就是一个内容。

scrollLeft和scrollTop

722

上图中箭头部分就是scrollTop,也就是向下滚动了多少px,页面向上隐藏了多少px

scrollLeft和scrollTop一般用于html对;众所周知在页面中是唯一的标签,不需要用document.querySelector去寻找,如id选择器和body,直接写成document.body即是一个对象。

id唯一,免寻找

1119

底层直接把id名字当做了dom对象名字,我们可以操作

html同样不需要,但是不能直接写为document.html.scrollTop,html得用documentElement代替,即写成document.documentElement.scrollTop,别问为什么就是这样规定。

注意:

1-scrollTop和scrollLeft可以直接赋值,即让用户打开网页就滚动一定距离。

723

2-scrollTop和scrollLeft返回的是数字,不带单位,赋值时同时不需要给单位,默认px

返回顶部按钮

724

1-第三步我本来还想用锚链接,id配合a来回到顶部,其实可以直接设置scrollTop等于0

2-父元素.children[x];父子节点children是一个数组,需要用数组形式来取子元素对象。

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            height: 3000px;
            background-color: skyblue;
        }

        a {
            display: none;
            width: 80px;
            height: 50px;
            background: #000;
            text-decoration: none;
            color: aliceblue;
            text-align: center;
            line-height: 50px;
            left: 90%;
            bottom: 60px;
            position: fixed;
        }
    </style>
</head>

<body>
    <div><a href="">回到顶部</a></div>
    <script>
        let backTop = document.querySelector('a')
        window.addEventListener('scroll', function () {
            let num = document.documentElement.scrollTop
            if (num > 500) {
                backTop.style.display = 'block'
            }
            else {
                backTop.style.display = 'none'
            }
        })
        backTop.addEventListener('click', function () {
            document.documentElement.scrollTop = 0
        })

    </script>
</body>

</html>

offset

使用scrollTop虽然可以取得滑动的像素,然后配合js显示出返回顶部,但是有一个缺点

上面的判断条件500是指定的,但是实际开发中,一般是当用户滑到某个元素内容区域,再进行”回到顶部“控件的显示,但这个内容区域的位置是变化的,所以需要用到offset来动态获取位置。

725

1-offsetWidth和offsetHeight 与scrollWidth/scrollHeight的区别是,前者是自身盒子高度(包括padding和border),后者scroll是盒子内容高度。

2-offsetTop/offsetLeft是只读无法修改的,很简单的道理,这个如果可以随便修改,布局不全乱套了。

3-offsetTop/offsetLeft获取的是获取元素到有定位的父级(父亲没有定位就找爷爷,都没有就以文档左上角为准)的上/左距离

导航栏案例

需求:当用户滑动到秒杀模块时,导航栏显示出来。

1-定位后的left/right/bottom/top是可以为负数的,让元素在页面以外,等相应条件满足再滑下来(使用tansition:all 1s),这个案例中的导航栏就会用到。

2-linear-gradient(red,blue),注意这里是括号,而且是给background-image设置才有效,不是给background-color设置。

3-因为导航栏要显示在内容的上面,根据层级 标准<浮动<定位,所以导航需要给一个固定定位,注意固定定位会脱标,然后块元素会被转换为行内块元素,所以导航盒子需要给宽。

726

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .container {
            margin: 0 auto;
            width: 1200px;
        }

        .content {
            background-color: pink;
            min-height: 1900px;
        }

        .nav {
            position: fixed;
            height: 40px;
            width: 100%;
            background-image: linear-gradient(pink,
                    skyblue);
            text-align: center;
            line-height: 40px;
            top: -40px;
            transition: all .3s;
        }

        .miaosha {
            width: 200px;
            height: 200px;
            background-color: skyblue;
            position: relative;
            top: 600px;
        }
    </style>
</head>

<body>
    <div class="nav">
        <p>我是顶部导航栏</p>
    </div>
    <div class="container">
        <div class="content">
            <!-- 秒杀模块,滑到这个模块。让导航栏显现 -->
            <div class="miaosha">
                我是秒杀模块
            </div>

        </div>
    </div>
    <script>
        let miaosha = document.querySelector('.miaosha')
        let nav = document.querySelector('.nav')
        window.addEventListener('scroll', function () {
            let num = document.documentElement.scrollTop
            console.log(miaosha.offsetTop)
            console.log(num)
            if (num >= miaosha.offsetTop) {
                nav.style.top = '0px'
            }
            else {
                nav.style.top = '-80px'
            }
        })
    </script>
</body>

</html>

电梯导航案例

犯错:js事件不生效

原因:找类选择器需要加点,但是增加删除classList的类名不需要加点。

犯错:for循环中i没有用let i =0 声明,而是直接写i = 0,导致有作用域链的问题,从而后面的content[i]无法识别。

在js中,如果某个变量没有var声明,会自动移到上一层作用域中去找这个变量的声明语句,如果找到,就是用,如果没找到,就继续向上寻找,一直查找到全局作用域为止,如果全局中仍然没有这个变量的声明语句,那么自动在全局作用域进行声明,这个就是js中的作用域链,也叫变量提升

因为我这里直接写i=0,上面也没有其他的声明i,所以默认也是全局作用域了

“所谓的变量提升(Hoisting)就是:在任何作用域中使用var声明的变量,都会被提升到其作用域最顶部,也就 是说该变量的作用域相当于其函数或者全局,但是其赋值操作还是在原先的位置”

734

735

736

所以原因是:i=0,通过作用域链变成了全局变量,点击事件是我们主动去触发的,但是循环是一直在运行的,我们点击之前,循环体早已经执行完。因为var的作用域是全局,所以i恒等于最后执行的那一个值。

这是一个同步和异步的问题,并不是绑定事件的时候通过循环i的不同值就绑定好了,那个绑定事件当我们点击触发的时候,还是会去找i

解决方法:let=0即可

727

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0px;
            padding: 0px;
        }

        .aside {
            position: fixed;
            width: 150px;
            /* 固定定位的top等是以浏览器窗口为参照物 */
            top: 50%;
            /* translate是以自身为参照物 */
            transform: translateY(-50%);
            text-align: center;
            line-height: 40px;
        }

        li {
            list-style: none;
            height: 40px;
            width: 100px;
            cursor: pointer;
        }

        .content {
            width: 500px;
            min-height: 1500px;
            margin: 0px 430px;
        }

        .content div {
            width: 500px;
            height: 300px;
            background-color: pink;
            margin-top: 20px;
        }

        .active {
            background-color: skyblue;
        }
    </style>
</head>

<body>
    <div class="content">
        <div>男装</div>
        <div>女装</div>
        <div>电子产品</div>
        <div>美食</div>
    </div>
    <div class="aside">
        <ul>
            <li class="active">男装</li>
            <li>女装</li>
            <li>电子产品</li>
            <li>美食</li>
        </ul>
    </div>
    <script>
        let contents = document.querySelectorAll('.content div')
        let lis = document.querySelectorAll('li')
        // console.log(lis)
        for (let i = 0; i < lis.length; i++) {
            lis[i].addEventListener('click', function () {
                // 可以用排他原则,但是我设置了默认active,可以用以下语句更简单
                document.querySelector('.active').classList.remove('active')
                this.classList.add('active')
                console.log(contents[i])
                document.documentElement.scrollTop = contents[i].offsetTop

            })
        }
    </script>
</body>

</html>

client

728

1-clientWidth/clientHeight是获取元素可视区域的宽高,不包含滚动条和边框等。

2-clientLeft和clientTop获取的就是盒子可视区域到盒子最外边框的宽度,其实就是滚动条和边框的大小,所以很少使用。

综合案例轮播图

新知识点和技巧

1-轮播图目前我会两种方法实现,一种是给多张图片放在一个盒子里,然后浮动,让它们在一排显示,再使用overflow:hidden来隐藏超出盒子部分,然后通过transform:translateX()来实现不同图片的显示。(可以设置用户左右滑动事件,但是到了最后一张怎么办呢?如何做到无缝轮播)

733

我们可以通过js复制第一张和最后一张(注意不要写硬编码,因为不好维护修改,最好用变量代替)

当用户滑到最后一张即轮播图3的时候,以极快的速度让轮播图移动到前面那个轮播图3即可(这种变化用户是感觉不到的)

向左滑动原理一样,当在图1再向右滑动,按理要到后面的图3,所以我们要以极快的速度,从前面的图1,转换为后面的图1即可。

2-第二种方法就是下面用到的,让图片绝对定位到一起,利用opacity来决定谁显示。(无法让用户左右滑动)

3-轮播图的自动轮播就用定时器来操作。

4**-直接调用监听函数**,如下面代码中dom对象next设置了click监听函数,我们可以通过next.click()直接调用

需求分析:

729

730

731

思路步骤:

1-先分清楚样式结构,这里只自己写js思路,样式用老师现有代码。

732

这个轮播图分为两大部分,一个是图片部分(包含图片和图片描述)和指示器部分(用户自行选择轮播图的显示,和大多轮播图那个小圆点一样,只是给了图片来代替)

2-其中所有的图包含在ul中的每个li中,通过给予绝对定位,全部重叠到一起,通过opacity的样式来决定显示哪一张。(为什么不用hidden或者display:none什么的呢,因为opacity有动画效果,可以设置transition)

3-指示器indicater图片的兄弟标签可以加一个span(背景设置灰色)当做遮罩,然后通过绝对定位和图片重叠到一起。即li相对定位,包含图片和遮罩span(两个都绝对定位)。

我的代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>QQ音乐轮播图</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        li {
            list-style: none;
        }

        .main {
            width: 700px;
            margin: auto;
            background: #000;
        }

        .slides {
            height: 320px;
            position: relative;
        }

        .slides ul li {
            /* display: none; */
            position: absolute;
            top: 0;
            left: 0;
            opacity: 0;
            /* 这里实现淡入淡出的关键 */
            transition: all .3s;
        }


        .slides li.active {
            /* display: block; */
            opacity: 1;
        }

        .slides .extra {
            width: 700px;
            height: 53px;
            line-height: 53px;
            position: absolute;
            bottom: 0px;
            background-color: rgba(0, 0, 0, 0.8);
            z-index: 10;
        }

        .slides .extra h3 {
            width: 82%;
            margin: 0;
            margin-right: 20px;
            padding-left: 20px;
            color: #98E404;
            font-size: 28px;
            float: left;
            font-weight: 500;
            font-family: "Microsoft Yahei", Tahoma, Geneva;
        }

        .slides .extra a {
            width: 30px;
            height: 29px;
            display: block;
            float: left;
            margin-top: 12px;
            margin-right: 3px;
            background-color: #fff;
            background-image: url(./assets/icon_focus_switch.png);
        }

        .slides .extra .prev {
            background-position: 0 0;
        }

        .slides .extra .prev:hover {
            background-position: -30px 0;
        }

        .slides .extra .next {
            background-position: -60px 0;
        }

        .slides .extra .next:hover {
            background-position: -90px 0;
        }

        .indicator {
            padding: 10px 0;
        }

        .indicator ul {
            list-style-type: none;
            margin: 0 0 0 4px;
            padding: 0;
            overflow: hidden;
        }

        .indicator ul li {
            position: relative;
            float: left;
            width: 60px;
            margin: 0 4px 0 5px;
            text-align: center;

            cursor: pointer;
        }

        .indicator li img {
            display: block;
            border: 0;
            text-align: center;
            width: 60px;
        }

        .indicator li .mask {
            width: 60px;
            height: 60px;
            position: absolute;
            top: 0;
            left: 0;
            background-color: rgba(0, 0, 0, 0.4);
        }

        .indicator li .border {
            display: none;
            width: 54px;
            position: absolute;
            bottom: 0;
            left: 0;
            z-index: 20;
            border: 3px solid #98E404;
        }

        /* li里面的mask 和 border 刚开始都是显示的 */
        /* 我们写一个样式css */
        .indicator .active .mask {
            display: none;
        }

        .indicator .active .border {
            display: block;
        }
    </style>
</head>

<body>
    <div class="main">
        <div class="slides">
            <ul>
                <li class="active"><a href="#"><img src="./assets/b_01.jpg" alt="第1张图的描述信息"></a></li>
                <li><a href="#"><img src="./assets/b_02.jpg" alt="第2张图的描述信息"></a></li>
                <li><a href="#"><img src="./assets/b_03.jpg" alt="第3张图的描述信息"></a></li>
                <li><a href="#"><img src="./assets/b_04.jpg" alt="第4张图的描述信息"></a></li>
                <li><a href="#"><img src="./assets/b_05.jpg" alt="第5张图的描述信息"></a></li>
                <li><a href="#"><img src="./assets/b_06.jpg" alt="第6张图的描述信息"></a></li>
                <li><a href="#"><img src="./assets/b_07.jpg" alt="第7张图的描述信息"></a></li>
                <li><a href="#"><img src="./assets/b_08.jpg" alt="第8张图的描述信息"></a></li>
                <li><a href="#"><img src="./assets/b_09.jpg" alt="第9张图的描述信息"></a></li>
                <li><a href="#"><img src="./assets/b_10.jpg" alt="第9张图的描述信息"></a></li>
            </ul>

            <div class="extra">
                <h3>第1张图的描述信息</h3>
                <a class="prev" href="javascript:;"></a>
                <a class="next" href="javascript:;"></a>
            </div>
        </div>
        <div class="indicator">
            <ul>
                <li class="active">
                    <img src="assets/s_01.jpg">
                    <span class="mask"></span>
                    <span class="border"></span>
                </li>
                <li>
                    <img src="assets/s_02.jpg">
                    <span class="mask"></span>
                    <span class="border"></span>
                </li>
                <li>
                    <img src="assets/s_03.jpg">
                    <span class="mask"></span>
                    <span class="border"></span>
                </li>
                <li>
                    <img src="assets/s_04.jpg">
                    <span class="mask"></span>
                    <span class="border"></span>
                </li>
                <li>
                    <img src="assets/s_05.jpg">
                    <span class="mask"></span>
                    <span class="border"></span>
                </li>
                <li>
                    <img src="assets/s_06.jpg">
                    <span class="mask"></span>
                    <span class="border"></span>
                </li>
                <li>
                    <img src="assets/s_07.jpg">
                    <span class="mask"></span>
                    <span class="border"></span>
                </li>
                <li>
                    <img src="assets/s_08.jpg">
                    <span class="mask"></span>
                    <span class="border"></span>
                </li>
                <li>
                    <img src="assets/s_09.jpg">
                    <span class="mask"></span>
                    <span class="border"></span>
                </li>
                <li>
                    <img src="assets/s_10.jpg">
                    <span class="mask"></span>
                    <span class="border"></span>
                </li>
            </ul>
        </div>
    </div>
    <script>
        // 1-让indicater鼠标移入后高亮,即加上active类,让mask消失
        // 获取indicater中的每个li
        let lis = document.querySelectorAll('.indicator li')
        let piclis = document.querySelectorAll('.slides  li')
        let text = document.querySelector('.extra h3')
        let next = document.querySelector('.next')
        let prev = document.querySelector('.prev')
        let main = document.querySelector('.main')
        // 给这些li添加绑定事件,同时绑定多个,用for循环
        for (let i = 0; i < lis.length; i++) {
            lis[i].addEventListener('mouseenter', function () {
                // 排他原则,或让当前有active的对象去除active样式
                document.querySelector('.indicator .active').classList.remove('active')
                // 给当前鼠标移入的li添加active类名
                this.classList.add('active')
                // 2-让轮播图随着indicater变化
                document.querySelector('.slides ul .active').classList.remove('active')
                // 给当前鼠标移入的li添加active类名,这里的active和上面的css是不同的,各自写了带active交集选择器不同的css语句
                piclis[i].classList.add('active')
                // 让图片说明变化
                text.innerHTML = `${i + 1}张图的描述信息`
                // 4-:解决一个BUG
                // 点击右侧按钮可以实现播放下一张,但是鼠标经过前面的,播放就会乱序
                // 解决方案:  让变化量 index 重新赋值为 当前鼠标经过的索引号
                // 鼠标经过了那个小li 他的索引号就是 i 
                // 右侧按钮是通过 index 来了控制播放的
                index = i
            })
        }
        // 3- 点击按钮播放上一张下一张
        // 定义一个index变量记录当前是第几张图,让相应的indicater和图片显示
        // 这个index一定要是个全局变量,因为后面很多地方都需要用到它,也需要它来连接
        let index = 0
        next.addEventListener('click', function () {
            index++
            if (index === lis.length) {
                index = 0
            }
            common()
        })
        prev.addEventListener('click', function () {
            index--
            if (index === -1) {
                index = lis.length - 1
            }
            common()
        })
        // 5-next和prev函数中也有很多代码一样,后续定时器轮播也需要用到,所以封装一个公用函数
        function common() {
            document.querySelector('.indicator .active').classList.remove('active')
            lis[index].classList.add('active')
            document.querySelector('.slides ul .active').classList.remove('active')
            piclis[index].classList.add('active')
            text.innerHTML = `${index + 1}张图的描述信息`
        }
        console.log(next)
        // 6-轮播图
        let timer = setInterval(function () {
            // 这里直接使用next.click(),因为当给next对象添加了一个点击事件,这个对象中就有了一个这样的方法
            next.click()
        }, 1000)
        // 7-鼠标移入轮播图盒子范围清除定时器 停止轮播,移除后再开启定时器
        main.addEventListener('mouseenter', function () {
            clearInterval(timer)
        })
        main.addEventListener('mouseleave', function () {
            timer = setInterval(function () {
                // 这里直接使用next.click(),因为当给next对象添加了一个点击事件,这个对象中就有了一个这样的方法
                next.click()
            }, 1000)
        })
    </script>
</body>

</html>

参考代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>QQ音乐轮播图</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    li {
      list-style: none;
    }

    .main {
      width: 700px;
      margin: auto;
      background: #000;
    }

    .slides {
      height: 320px;
      position: relative;
    }

    .slides ul li {
      /* display: none; */
      position: absolute;
      top: 0;
      left: 0;
      opacity: 0;
      /* 这里实现淡入淡出的关键 */
      transition: all .3s;
    }


    .slides li.active {
      /* display: block; */
      opacity: 1;
    }

    .slides .extra {
      width: 700px;
      height: 53px;
      line-height: 53px;
      position: absolute;
      bottom: 0px;
      background-color: rgba(0, 0, 0, 0.8);
      z-index: 10;
    }

    .slides .extra h3 {
      width: 82%;
      margin: 0;
      margin-right: 20px;
      padding-left: 20px;
      color: #98E404;
      font-size: 28px;
      float: left;
      font-weight: 500;
      font-family: "Microsoft Yahei", Tahoma, Geneva;
    }

    .slides .extra a {
      width: 30px;
      height: 29px;
      display: block;
      float: left;
      margin-top: 12px;
      margin-right: 3px;
      background-image: url(./assets/icon_focus_switch.png);
    }

    .slides .extra .prev {
      background-position: 0 0;
    }

    .slides .extra .prev:hover {
      background-position: -30px 0;
    }

    .slides .extra .next {
      background-position: -60px 0;
    }

    .slides .extra .next:hover {
      background-position: -90px 0;
    }

    .indicator {
      padding: 10px 0;
    }

    .indicator ul {
      list-style-type: none;
      margin: 0 0 0 4px;
      padding: 0;
      overflow: hidden;
    }

    .indicator ul li {
      position: relative;
      float: left;
      width: 60px;
      margin: 0 4px 0 5px;
      text-align: center;

      cursor: pointer;
    }

    .indicator li img {
      display: block;
      border: 0;
      text-align: center;
      width: 60px;
    }

    .indicator li .mask {
      width: 60px;
      height: 60px;
      position: absolute;
      top: 0;
      left: 0;
      background-color: rgba(0, 0, 0, 0.4);
    }

    .indicator li .border {
      display: none;
      width: 54px;
      position: absolute;
      bottom: 0;
      left: 0;
      z-index: 20;
      border: 3px solid #98E404;
    }

    /* li里面的mask 和 border 刚开始都是显示的 */
    /* 我们写一个样式css */
    .indicator .active .mask {
      display: none;
    }

    .indicator .active .border {
      display: block;
    }
  </style>
</head>

<body>
  <div class="main">
    <div class="slides">
      <ul>
        <li class="active"><a href="#"><img src="./assets/b_01.jpg" alt="第1张图的描述信息"></a></li>
        <li><a href="#"><img src="./assets/b_02.jpg" alt="第2张图的描述信息"></a></li>
        <li><a href="#"><img src="./assets/b_03.jpg" alt="第3张图的描述信息"></a></li>
        <li><a href="#"><img src="./assets/b_04.jpg" alt="第4张图的描述信息"></a></li>
        <li><a href="#"><img src="./assets/b_05.jpg" alt="第5张图的描述信息"></a></li>
        <li><a href="#"><img src="./assets/b_06.jpg" alt="第6张图的描述信息"></a></li>
        <li><a href="#"><img src="./assets/b_07.jpg" alt="第7张图的描述信息"></a></li>
        <li><a href="#"><img src="./assets/b_08.jpg" alt="第8张图的描述信息"></a></li>
        <li><a href="#"><img src="./assets/b_09.jpg" alt="第9张图的描述信息"></a></li>
        <li><a href="#"><img src="./assets/b_10.jpg" alt="第9张图的描述信息"></a></li>
      </ul>

      <div class="extra">
        <h3>第1张图的描述信息</h3>
        <a class="prev" href="javascript:;"></a>
        <a class="next" href="javascript:;"></a>
      </div>
    </div>
    <div class="indicator">
      <ul>
        <li class="active">
          <img src="assets/s_01.jpg">
          <span class="mask"></span>
          <span class="border"></span>
        </li>
        <li>
          <img src="assets/s_02.jpg">
          <span class="mask"></span>
          <span class="border"></span>
        </li>
        <li>
          <img src="assets/s_03.jpg">
          <span class="mask"></span>
          <span class="border"></span>
        </li>
        <li>
          <img src="assets/s_04.jpg">
          <span class="mask"></span>
          <span class="border"></span>
        </li>
        <li>
          <img src="assets/s_05.jpg">
          <span class="mask"></span>
          <span class="border"></span>
        </li>
        <li>
          <img src="assets/s_06.jpg">
          <span class="mask"></span>
          <span class="border"></span>
        </li>
        <li>
          <img src="assets/s_07.jpg">
          <span class="mask"></span>
          <span class="border"></span>
        </li>
        <li>
          <img src="assets/s_08.jpg">
          <span class="mask"></span>
          <span class="border"></span>
        </li>
        <li>
          <img src="assets/s_09.jpg">
          <span class="mask"></span>
          <span class="border"></span>
        </li>
        <li>
          <img src="assets/s_10.jpg">
          <span class="mask"></span>
          <span class="border"></span>
        </li>
      </ul>
    </div>
  </div>
  <script>
    // 轮播图开始啦
    // 需求①:小图标鼠标经过事件
    //   鼠标经过小图片,当前高亮,其余兄弟变淡  添加类
    let lis = document.querySelectorAll('.indicator li')
    let piclis = document.querySelectorAll('.slides ul li')
    let text = document.querySelector('.extra h3')
    let next = document.querySelector('.next')
    let prev = document.querySelector('.prev')
    let main = document.querySelector('.main')

    // 给多个小li绑定事件
    for (let i = 0; i < lis.length; i++) {
      lis[i].addEventListener('mouseenter', function () {
        // 选出唯一的那个active ,删除类
        document.querySelector('.indicator .active').classList.remove('active')
        // 鼠标经过谁,谁加上active 这个类
        this.classList.add('active')

        // 需求② :大图片跟随变化  一定要放到鼠标经过事件里面
        // 对应的大图片跟着显示,如果想要过渡效果,可以使用opacity效果,可以利用CSS淡入      淡出的效果,还是添加类
        // 选出唯一的那个active ,删除类
        document.querySelector('.slides ul .active').classList.remove('active')
        // 对应序号的那个 li,谁加上active 这个类
        piclis[i].classList.add('active')
        text.innerHTML = `${i + 1}张图的描述信息`

        // 需求④:解决一个BUG
        // 点击右侧按钮可以实现播放下一张,但是鼠标经过前面的,播放就会乱序
        // 解决方案:  让变化量 index 重新赋值为 当前鼠标经过的索引号
        // 鼠标经过了那个小li 他的索引号就是 i 
        // 右侧按钮是通过 index 来了控制播放的
        index = i
      })
    }


    // 需求③:右侧按钮播放效果
    //   点击右侧按钮,可以自动播放下一张图片
    //   需要一个变化量  index 不断自增
    //   然后播放下一张图片
    //   如果到了最后一张,必须要还原为第1张图片
    //   教你一招: 索引号 = 索引号 % 数组长度 (放到播放前面)
    let index = 0  // 全局变量  信号量 控制器 为了给 右侧按钮和左侧按钮同时使用
    next.addEventListener('click', function () {
      index++
      // 选出 index 小图片 做操作
      // console.log(index)
      // if (index === lis.length) {
      //   index = 0
      // }
      index = index % lis.length
      common()

    })

    // 需求⑤:左侧按钮播放效果
    //   点击左侧按钮,可以自动播放上一张图片
    //   需要一个变化量  index 不断自减
    //   然后播放上一张图片
    //   如果到了第一张,必须要从最后一张播放
    //   教你一招: 索引号 = (数组长度 + 索引号) % 数组长度
    prev.addEventListener('click', function () {
      index--
      // 选出 index 小图片 做操作
      // console.log(index)
      if (index < 0) {
        index = lis.length - 1
      }
      // index = (lis.length + index) % lis.length
      common()

    })

    // 需求⑥:
    //   因为左侧按钮和右侧按钮里面有大量相同的操作,可以抽取封装一个函数 common
    function common() {
      document.querySelector('.indicator .active').classList.remove('active')
      lis[index].classList.add('active')
      // 选出 index 大图片 做操作
      document.querySelector('.slides ul .active').classList.remove('active')
      piclis[index].classList.add('active')
      text.innerHTML = `${index + 1}张图的描述信息`
    }



    // 需求⑦:开启定时器
    //   其实定时器自动播放,就相当于点击了右侧按钮,此时只需要, next.click()
    let timer = setInterval(function () {
      // 自动调用右侧按钮的点击事件
      next.click()
    }, 1000)
    // 需求⑧:
    //   鼠标经过停止定时器 (清除定时器)

    main.addEventListener('mouseenter', function () {
      clearInterval(timer)
    })
    //   鼠标离开开启定时器 (开启定时器)
    main.addEventListener('mouseleave', function () {
      timer = setInterval(function () {
        // 自动调用右侧按钮的点击事件
        next.click()
      }, 1000)
    })
  </script>
</body>

</html>

文章作者: 瑾年
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 周东奇 !
免责声明: 本站所发布的一切内容,包括但不限于IT技术资源,网络攻防教程及相应程序等文章仅限用于学习和研究目的:不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。本站部分信息与工具来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如有侵权请邮件(jinnian770@gmail.com)与我们联系处理。
  目录