DOM- 网页特效

1. 滚动事件和加载事件

1. 滚动事件scroll

  1. 当页面进行滚动时触发的事件

  2. 很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部

  3. 监听整个页面滚动给 window 或 document 加

  4. 监听某个元素的内部滚动直接给某个元素加即可

1
2
3
4
5
6
7
8
9
监听整个页面滚动
// 1. 滚动事件 监听整个页面滚动 固定导航/返回顶部
window.addEventListener('scroll', function () {
console.log(1)
})
let num1 = document.querySelector('.box')
num1.addEventListener('scroll', function () {
console.log(2)
})

2. 加载事件load

  1. 加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件

  2. 有些时候需要等页面资源全部处理完了做一些事情

  3. 老代码喜欢把 script 写在 head 中,这时候直接找 dom 元素找不到

  4. 注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件

监听页面所有资源加载完毕:

1
2
3
4
5
6
7
8
监听整个页面资源给 window
// 2. 加载事件 监听页面资源加载完毕才执行load事件
// 也可以针对别的资源绑定load事件
// 把js写在head上面 导致dom元素找不到 用load事件
let n1 = document.querySelector('.box')
window.addEventListener('load', function () {
console.log(11)
})

3. 加载事件DOMContentLoaded

  1. 当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表 、图像等完全加载

监听页面DOM加载完毕:

1
2
3
4
5
document 添加 DOMContentLoaded 事件
// 2. 加载事件 等HTML文档加载完后再加载 无需等样式 图片就可以加载
document.addEventListener('DOMContentLoaded', function () {
console.log(3)
})

2. scroll家族

  1. 我们想要页面滚动一段距离,比如100px,就让某些元素显示隐藏, 就可以使用scroll 来检测页面滚动的距离~~~

  2. 获取宽高: 获取元素的内容总宽高(不包含滚动条)返回值不带单位

  3. scrollWidth和scrollHeight

获取位置:
  1. 获取元素内容往左、往上滚出去看不到的距离

  2. scrollLeft和scrollTop

  3. 这两个属性是可以修改的

1
2
3
4
5
6
7
8
9
10
11
// 1. scroll家族 (了解)
let num1 = document.querySelector('.box')
// // 当前宽度 不包含滚动条
console.log(num1.scrollWidth)
// // 内容高度
console.log(num1.scrollHeight)

// // 2. 被卷去的头部和左侧
num1.addEventListener('scroll', function () {
console.log(this.scrollTop)
})
开发中,我们经常检测页面滚动的距离,比如页面滚动100像素,就可以显示一个元素,或者固定一个元素
  1. document.documentElement HTML 文档返回对象为HTML元素
1
2
3
4
5
6
7
// 3. 检测页面滚动的距离
window.addEventListener('scroll', function () {
// 返回HTML元素距离
console.log(document.documentElement.scrollTop)
// 可以给值/修改 但不要带单位
document.documentElement.scrollTop = 200
})
  1. 被卷去的头部或者左侧用那个属性?是否可以读取和修改?

  2. 可以读取,也可以修改(赋值)

页面滚动显示返回顶部按钮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
需求:当页面滚动500像素,就显示返回顶部按钮,否则隐藏, 同时点击按钮,则返回顶部
①:用到页面滚动事件
②:检测页面滚动大于等于100像素,则显示按钮
③:点击按钮,则让页面的scrollTop 重置为 0
<div class="content"></div>
<div class="backtop">
<img src="./images/close2.png" alt="">
<a href="javascript:;"></a>
</div>
let btn = document.querySelector('.backtop')
// 1. 页面滚动事件
window.addEventListener('scroll', function () {
// 2. 页面检测滚动距离
let num1 = document.documentElement.scrollTop
// 3. 判断显示隐藏
// 如果大于200 就显示 小于隐藏
if (num1 >= 200) {
btn.style.display = 'block'
} else {
btn.style.display = 'none'
}
})

// 4. 点击链接返回顶部
btn.children[1].addEventListener('click', function () {
document.documentElement.scrollTop = 0
})

3.offset家族

  1. 使用场景: 前面案例滚动多少距离,都是我们自己算的,最好是页面 滚动到某个元素,就可以做某些事

  2. 简单说,就是通过js的方式,得到元素在页面中的位置 这样我们可以做,页面滚动到这个位置,就可以返回 顶部的小盒子显示…

获取宽高:

  1. 获取元素的自身宽高、包含元素自身设置的宽高、padding、border, offsetWidth和offsetHeight
1
2
3
4
5
6
// 1. offset家族 宽高 (了解)
let num1 = document.querySelector('.box')
// 盒子大小 = 盒子本身宽高 + padding + border
// 盒子多大 offset就多大
console.log(num1.offsetWidth)
console.log(num1.offsetHeight)

获取位置:

  1. 获取元素距离自己定位父级元素的左、上距离

  2. offsetLeft和offsetTop 注意是只读属性

1
2
3
// 2. 位置以带定位的父级 如果没有就以左上角为准
console.log(num1.offsetTop)
console.log(num1.offsetLeft)

仿京东固定导航栏案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
当页面滚动到秒杀模块,导航栏自动滑入,否则滑出
①:用到页面滚动事件
②:检测页面滚动大于等于 秒杀模块的位置 则滑入,否则滑出
<div class="header">我是顶部导航栏</div>
<div class="content">
<div class="sk">秒杀模块</div>
</div>
<div class="backtop">
<img src="./images/close2.png" alt="">
<a href="javascript:;"></a>
</div>
let box = document.querySelector('.sk')
let head = document.querySelector('.header')
// 1.页面滚动事件
window.addEventListener('scroll', function () {
// 2.检测页面滚动距离 >= 秒杀模块的offsetTop 则划入
if (document.documentElement.scrollTop >= box.offsetTop) {
// 3.如果大于则显示 小于则-80px
head.style.top = '0px'
} else {
head.style.top = '-80px'
}
})

电梯导航案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
需求:点击可以页面调到指定效果
①:点击当前 小导航,当前添加active,其余移除active
②:得到对应 内容 的 offsetTop值
③:让页面的 scrollTop 走到 对应 内容 的 offsetTop
<div class="aside">
<div class="item active">男装/女装</div>
<div class="item">儿童服装/游乐园</div>
<div class="item">电子产品</div>
<div class="item">电影/美食</div>
</div>
<div class="content">
<div class="neirong content1">男装/女装</div>
<div class="neirong content2">儿童服装/游乐园</div>
<div class="neirong content3">电子产品</div>
<div class="neirong content4">电影/美食</div>
</div>
let btn = document.querySelectorAll('.item')
let btn1 = document.querySelectorAll('.neirong')
// 1. 点击谁谁添加类
for (let num1 = 0; num1 < btn.length; num1++) {
btn[num1].addEventListener('click', function () {
document.querySelector('.aside .active').classList.remove('active')
this.classList.add('active')
// 2. 右侧内容跟随走动
// 让页面滚动对应offsettop值位置
document.documentElement.scrollTop = btn1[num1].offsetTop
})
}

4.client家族

  1. 获取宽高:获取元素的可见部分宽高(不包含边框,滚动条等), clientWidth和clientHeight

  2. 获取位置: 获取左边框和上边框宽度, clientLeft和clientTop 注意是只读属性

1
2
3
4
5
6
7
let num1 = document.querySelector('.box')
// 可见区域的宽高 不包含滚动条 边框...
console.log(num1.clientWidth)
console.log(num1.clientHeight)
// 3. client TOP/Left (了解) 就是边框的宽高
console.log(num1.clientTop)
console.log(num1.clientLeft)

会在窗口尺寸改变的时候触发事件:resize

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 2. resize事件 当窗口变化时触发的事件
window.addEventListener('resize', function () {
// 检测屏幕宽度
console.log(document.documentElement.clientWidth)
// 检测页面的宽度不同而改变颜色
let num2 = document.documentElement.clientWidth
if (num2 >= 1000) {
document.body.style.backgroundColor = 'skyblue'
} else if (num2 >= 850) {
document.body.style.backgroundColor = 'pink'
} else {
document.body.style.backgroundColor = 'green'
}
})

5. 三大家族的区别

1. offset家族

  1. 获取元素自身大小:包括自身设置的宽高、padding、border

  2. 获取元素距离定位父级的左和上距离 只读属性

2. scroll家族

  1. 获取元素内容的总大小

  2. 获取元素向左向上滚出去看不见的距离 可读写属性

3. client家族

  1. 获取元素可见区域的大小

  2. 获取元素左、上边框距离 只读属性

6. 轮播图案例

  1. 需求①:小图标鼠标经过事件

  2. 需求② :大图片跟随变化

  3. 需求③:右侧按钮播放效果

  4. 需求④:解决一个BUG

  5. 需求⑤:左侧按钮播放效果

  6. 需求⑥: 因为左侧按钮和右侧按钮里面有大量相同的操作,可以抽取封装一个函数 common

  7. 需求⑦:开启定时器需求

  8. ⑧: 鼠标经过停止定时器 (清除定时器) 鼠标离开开启定时器 (开启定时器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<div class="main">
<div class="slides">
<ul>
<li class="active"><a href="#"><img src="./images/b_01.jpg" alt="第1张图的描述信息"></a></li>
<li><a href="#"><img src="./images/b_02.jpg" alt="第2张图的描述信息"></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="images/s_01.jpg">
<span class="mask"></span>
<span class="border"></span>
</li>
<li>
<img src="images/s_02.jpg">
<span class="mask"></span>
<span class="border"></span>
</li>
</ul>
</div>
</div>
let xl = document.querySelectorAll('.indicator li')
let dl = document.querySelectorAll('.slides ul li')
let text = document.querySelector('.extra h3')
let btn = document.querySelector('.next')
let btn1 = document.querySelector('.prev')
let main = document.querySelector('.main')
for (let num1 = 0; num1 < xl.length; num1++) {
// 1.鼠标经过小图片变高亮
xl[num1].addEventListener('mouseenter', function () {
document.querySelector('.indicator .active').classList.remove('active')
this.classList.add('active')
// 2. 鼠标经过当前小图片后大图片变化
// 利用opacity实现淡入淡出效果
document.querySelector('.slides .active').classList.remove('active')
dl[num1].classList.add('active')
// 3. 鼠标经过图片 文字改变
text.innerHTML = `第${num1 + 1}张图的描述信息`

// 6. 解决Bug 如果鼠标经过后 再次点击播放会乱序
// 让index重新赋值为 当前鼠标经过索引号
index = num1
})
}

// 4. 右侧按钮点击事件
// 全局变化量变量 不断自增 控制器/给左右按钮同时使用
let index = 0
btn.addEventListener('click', function () {
index++ // 变量点击后自增

// 1. 解决点击最后一张后报错 等于10之后index为0
if (index == 10) {
index = 0
}
// 2. // 10 10 余 0
// index = index % 10
fn()
})

// 5.左侧按钮点击事件
btn1.addEventListener('click', function () {
index--
if (index < 0) {
index = 9
}
// 10 + -1 = 9 % 10 余 1
// index = (10 + index) % xl.length
fn()
})

// 6. 因为左右按钮有大量相同代码 可以封装成函数 然后调用
function fn() {
// 选出 index 大/小图片 排它思想
document.querySelector('.indicator .active').classList.remove('active')
xl[index].classList.add('active')
document.querySelector('.slides .active').classList.remove('active')
dl[index].classList.add('active')
text.innerHTML = `第${index + 1}张图的描述信息`
}

// 7. 开启轮播定时器
let timer = setInterval(function () {
// 自动调用右侧按钮点击事件
btn.click()
}, 800)

// 如果不清除 点击哪个就不会停止
// 8.鼠标经过清除定时器
main.addEventListener('mouseenter', function () {
clearInterval(timer)
})

// 9. 鼠标经过开启定时器
main.addEventListener('mouseleave', function () {
// 直接再开启一个定时器 不要重新赋值了
timer = setInterval(function () {
btn.click()
}, 800)
})

本节单词:

  1. scroll
  2. window
  3. load
  4. DOMContentLoaded
  5. offset
  6. client
  7. resize