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搭配使用才会最方便最简洁,效果最好。
滚动和加载事件
其中window也可以换成任意一个有滚动条的元素对象。如一个div内容超出盒子,overflow:auto后有滚动条也可用此事件监听。
加载事件
这里是load事件,给window加则是等整个window,包括图片,外联css和js等都加载完毕,再执行事件函数。
作用:有时页面资源没加载完,我们是做不了事情的,比如一个图片都没加载出来,你没办法去操作它;其次是老代码js写在body前面,body中的dom树结构节点都没有,怎么可能被js操作。
拓展:上面是给window添加load事件,等window加载完就执行;当然也可以给其他对象添加,如一个图片img.addEventListener(‘load’,function(){}),就是等这个图片加载完再执行。
DOMContentLoaded
DOMContentLoaded和load的区别就是,前者是 使用的对象中的dom树节点加载完毕即可,如div这些标签加载完就行了;后者是外联css/js/图片等都加载完才可以。
注意事件大小写,写错就不生效的,一般是小驼峰,这个事件DOM全大写了
元素大小和位置
scroll
作用:获取用户滚动了多少像素,从而精准进行交互。
其中scrollWidth和scrollHeight是获取盒子对象内容的大小的,而非盒子大小
如上盒子是150x150,但是scrollHeight是336,因为内容超出了。
当内容没超出,如就一行字,内容就是150x150大小,不是说内容就是div里面的文字等,盒子本身就是一个内容。
scrollLeft和scrollTop
上图中箭头部分就是scrollTop,也就是向下滚动了多少px,页面向上隐藏了多少px
scrollLeft和scrollTop一般用于html对;众所周知在页面中是唯一的标签,不需要用document.querySelector去寻找,如id选择器和body,直接写成document.body即是一个对象。
id唯一,免寻找
底层直接把id名字当做了dom对象名字,我们可以操作
html同样不需要,但是不能直接写为document.html.scrollTop,html得用documentElement代替,即写成document.documentElement.scrollTop,别问为什么就是这样规定。
注意:
1-scrollTop和scrollLeft可以直接赋值,即让用户打开网页就滚动一定距离。
2-scrollTop和scrollLeft返回的是数字,不带单位,赋值时同时不需要给单位,默认px
返回顶部按钮
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来动态获取位置。
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-因为导航栏要显示在内容的上面,根据层级 标准<浮动<定位,所以导航需要给一个固定定位,注意固定定位会脱标,然后块元素会被转换为行内块元素,所以导航盒子需要给宽。
<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声明的变量,都会被提升到其作用域最顶部,也就 是说该变量的作用域相当于其函数或者全局,但是其赋值操作还是在原先的位置”
所以原因是:i=0,通过作用域链变成了全局变量,点击事件是我们主动去触发的,但是循环是一直在运行的,我们点击之前,循环体早已经执行完。因为var的作用域是全局,所以i恒等于最后执行的那一个值。
这是一个同步和异步的问题,并不是绑定事件的时候通过循环i的不同值就绑定好了,那个绑定事件当我们点击触发的时候,还是会去找i
解决方法:let=0即可
<!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
1-clientWidth/clientHeight是获取元素可视区域的宽高,不包含滚动条和边框等。
2-clientLeft和clientTop获取的就是盒子可视区域到盒子最外边框的宽度,其实就是滚动条和边框的大小,所以很少使用。
综合案例轮播图
新知识点和技巧
1-轮播图目前我会两种方法实现,一种是给多张图片放在一个盒子里,然后浮动,让它们在一排显示,再使用overflow:hidden来隐藏超出盒子部分,然后通过transform:translateX()来实现不同图片的显示。(可以设置用户左右滑动事件,但是到了最后一张怎么办呢?如何做到无缝轮播)
我们可以通过js复制第一张和最后一张(注意不要写硬编码,因为不好维护修改,最好用变量代替)
当用户滑到最后一张即轮播图3的时候,以极快的速度让轮播图移动到前面那个轮播图3即可(这种变化用户是感觉不到的)
向左滑动原理一样,当在图1再向右滑动,按理要到后面的图3,所以我们要以极快的速度,从前面的图1,转换为后面的图1即可。
2-第二种方法就是下面用到的,让图片绝对定位到一起,利用opacity来决定谁显示。(无法让用户左右滑动)
3-轮播图的自动轮播就用定时器来操作。
4**-直接调用监听函数**,如下面代码中dom对象next设置了click监听函数,我们可以通过next.click()直接调用
需求分析:
思路步骤:
1-先分清楚样式结构,这里只自己写js思路,样式用老师现有代码。
这个轮播图分为两大部分,一个是图片部分(包含图片和图片描述)和指示器部分(用户自行选择轮播图的显示,和大多轮播图那个小圆点一样,只是给了图片来代替)
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>