PC端网页特效
# PC端网页特效
- 元素偏移量offset系列
- 元素可视区client系列
- 元素滚动scroll系列
- 封装简单动画函数
- 网页轮播图
# 元素偏移量offset系列
- 获取元素距离带有定位父元素的位置
- 获得元素自身的大小(宽度高度)
let father = document.querySelector('.father')
let son = document.querySelector('.son')
// 以带有定位的元素为准 如果没有父亲或者父亲没有定位 以body为准
console.log(son.offsetLeft)
let w = document.querySelector('.w')
// 得到元素的大小 宽度 高度 包含padding + border + width
console.log(w.offsetWidth)
console.log(w.offsetHeight)
// 返回带有定位的父亲 否则返回的是body
console.log(son.offsetParent) // 返回带有定位的父亲 否则返回的是body
console.log(son.parentNode) // 返回父亲 是最近一级父亲 亲爸爸 不关父亲有没有定位
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
offset和style的区别
offset
.offset 可以得到任意样式表中的样式值.
offset系列获得的数值是没有单位的.
offsetWidth 包含padding+border+width.
offsetWidth等属性是只读属性,只能获取不能赋值.
所以,我们想要获取元素大小位置,用offset更合适
style
.style只能得到行内样式表中的样式值
.style.width获得的是带有单位的字符串
.style.width 获得不包含padding和border的值
.style.width是可读写属性,可以获取也可以赋值
.所以,我们想要给元素更改值,则需要用style改变
/*
* 案例:获取鼠标在盒子里面坐标
* 1.首先得到鼠标在页面中的坐标(e.pageX,e.pageY)
* 2.其次得到盒子在页面中的聚集(box.offsetLeft,box.offsetTop)
* 3.用鼠标距离页面的坐标减去盒子在页面中的距离,得到鼠标在盒子内的坐标
* */
let box = document.querySelector('.box')
box.addEventListener('mousemove', function (e) {
console.log(e.pageX)
console.log(e.pageY)
console.log(box.offsetLeft)
let x = e.pageX - this.offsetLeft
let y = e.pageY - this.offsetTop
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
// 案例:拖动模态框
// 当鼠标按下,就获取鼠标在盒子内的坐标
title.addEventListener('mousedown', function (e) {
let x = e.pageX - login.offsetLeft
let y = e.pageY - login.offsetTop
// 鼠标移动的时候,把鼠标在页面中的坐标,减去鼠标在盒子内的坐标就是模态框的left值和top值
document.addEventListener('mousemove', move)
function move(e) {
login.style.left = e.pageX - x + 'px'
login.style.top = e.pageY - y + 'px'
}
// 鼠标弹起,让鼠标移动事件移除
document.addEventListener('mouseup', function () {
document.removeEventListener('mousemove', move)
})
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 案例:仿京东放大镜效果
/*
* 1.鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开隐藏两个盒子功能
* 2.黄色的遮挡层跟随鼠标功能
* 3.移动黄色遮挡层,大图片跟随移动功能
* */
// 当我们鼠标经过 preview 就显示和隐藏 mask遮挡层 和 big大盒子
pre.addEventListener('mouseover', function () {
mask.style.display = 'block'
big.style.display = 'block'
})
pre.addEventListener('mouseout', function (e) {
mask.style.display = 'none'
big.style.display = 'none'
})
// 1.先计算出鼠标在盒子内的坐标
pre.addEventListener('mousemove', function (e) {
// (1)先计算鼠标在盒子内的坐标
let x = e.pageX - this.offsetLeft
let y = e.pageY - this.offsetTop
// (2)减去盒子高度300的一半是150 就是我们mask的最终left和top值
// (3)我们mask移动的距离
let maskX = x - mask.offsetWidth / 2
let maskY = y - mask.offsetHeight / 2
// (4)如果x坐标小于0就让他停在0的位置
let maxkMax = pre.offsetWidth - mask.offsetWidth
if (maskX <= 0) {
maskX = 0
} else if (maskX >= maxkMax) {
maskX = maxkMax
}
if (maskY <= 0) {
maskY = 0
} else if (maskX >= maxkMax) {
maskX = maxkMax
}
mask.style.left = x - maskX + 'px'
mask.style.top = y - maskY + 'px'
/*
* 遮挡层移动距离 / 遮挡层最大移动距离 = 大图片移动距离 / 大图片最大移动距离
* 求大图片移动距离?
* 大图片移动距离 = 遮挡层移动距离 * 大图片最大移动距离 / 遮挡层最大移动距离
* */
// 大图
let bigImg = document.querySelector('.bigImg')
// 大图片最大移动距离
let bigMax = bigImg.offsetWidth - big.offsetWidth
// 大图片的移动距离
let bigX = maskX * bigMax / maxkMax
let bigY = maskY * bigMax / maxkMax
bigImg.style.left = -bigX + 'px'
bigImg.style.top = -bigY + 'px'
})
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
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
# client 系列
// 动态获取元素的边框大小、元素大小(不包含边框、包含padding)offsetWidth包含边框
// console.log(div.clientWidth)
// 立即执行函数(不需要调用,立马能够自己执行的函数)
// 创建一个独立的作用域 里面所有的变量都是局部变量 不会有命名冲突的情况
(function () {
})()
(function () {
}())
// 以下三种情况会刷新页面触发load事件
/*
* 1.a标签的超链接
* 2.F5或者刷新按钮(强制刷新)
* 3.前进后退按钮
* */
// 火狐浏览器 后退按钮不能刷新页面(因为他有个往返缓存 不仅保存着页面数据)
// pageshow 是我们重新加载页面触发的事件
// e.persisted返回的是true 就是说如果这个 页面是从缓存取过来的页面 也需要重新计算rem的大小
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# scroll系列
// scroll系列 (不包含边框 包含padding)
console.log(div.scrollHeight)
// scroll滚动事件 当我们滚动条发送变化会触发的时间
div.addEventListener('scroll', function () {
console.log(div.scrollTop)// 上侧距离
})
1
2
3
4
5
6
2
3
4
5
6
// 案例:固定侧边栏
// 元素被卷去的头部是element.scrollTop
// 页面被卷曲头部 通过window.pageYOffset
let sliderBar = document.querySelector('.slider-bar')
let banner = document.querySelector('.banner')
let bannerTop = banner.offsetTop
// 当我们侧边栏固定定位之后应该变化的数值
let sliderBarTop = sliderBar.offsetTop - bannerTop
// 获取main主题元素
let main = document.querySelector('.main')
let goBack = document.querySelector('.goBack')
let mainTop = main.offsetTop
document.addEventListener('scroll', function () {
// 当我们页面被卷去头部大于等于172 此时 侧边栏就可以改为固定定位
if (window.pageYOffset >= bannerTop) {
sliderBar.style.position = 'fixed'
sliderBar.style.top = sliderBarTop + 'px'
} else {
sliderBar.style.position = 'absolute'
sliderBar.style.top = '300px'
}
// 当我们页面滚动到main盒子 就显示goBack模块
if (window.pageYOffset >= mainTop) {
goBack.style.display = 'block'
} else {
goBack.style.display = 'none'
}
})
// 返回顶部
// 滚动窗口至文档中特定的位置
// window.scroll(x,y)
// 当我们点击了返回顶部模块
goBack.addEventListener('click', function () {
// 里面的x和y不跟单位,直接写数字
// window.scroll(0, 0)
// 因为是窗口滚动 所有对象是window
animate4(window,0)
/*
* 1.带有动画的返回顶部
* 2.此时可以继续使用我们封装的动画函数
* 3.只需要把所有的left相关的值,改为跟页面垂直滚动距离相关
* 4.页面滚动了多少,可以通过window.pageYOffset
* */
function animate4(obj, target,callback) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer)
obj.timer = setInterval(function () {
// 步长值写到定时器里面
// 步长值改为整数 不要出现小数的问题
let step = (target - window.pageYOffset) / 10
// 大于0向上 小于向下
step > 0 ? Math.ceil(step) : Math.floor(step)
if (window.pageYOffset === target) {
// 停止 本质是停止定时器
clearInterval(timer)
// 回调函数写道定时器结束里面
// if(callback){
// // 调用函数
// callback()
// }
callback && callback()
}
// 把每次加1 步长值改为一个慢慢变小的值在
// obj.style.left = window.pageYOffset + step + 'px'
window.scroll(0,window.pageYOffset + step)
}, 30)
}
})
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
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
/*
* 三大系列总结
* element.offsetWidth 返回自身包括padding、边框、内容区的宽度,返回数值不带单位
* element.clientWidth 返回自身包括padding、内容区的宽度,不含边框,返回数值不带单位
* element.scrollWidth 返回自身实际高度,不含边框,返回数值不带单位
* */
// offset 用于获取元素位置
// client 用户获取元素大小
// scroll 用于获取滚动距离
// window.pageXOffset 用于获取页面滚动的距离
// mouseenter和mouseover的区别
/*
* mouseover 经过自身盒子和子盒子都会触发
* mouseenter 经过自身盒子触发
* */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 动画函数封装
// 核心原理:通过定时器setInterval()不断移动盒子的位置
/*
* 1.获得盒子当前位置
* 2.让盒子在当前位置加上一个移动距离
* 3.利用定时器不断重复这个操作
* 4.加一个结束定时器的条件
* 5.注意:此元素需要添加定位,才能使用element.style.left
* */
let div = document.querySelector('div')
let timer = setInterval(function () {
if (div.offsetLeft >= 400) {
// 停止 本质是停止定时器
clearInterval(timer)
}
div.style.left = div.offsetLeft + 1 + 'px'
}, 30)
// 4.2动画函数简单封装
// 传递2个参数:动画对象和移动到的距离
function animate(obj, target) {
let timer = setInterval(function () {
if (obj.offsetLeft >= target) {
// 停止 本质是停止定时器
clearInterval(timer)
}
obj.style.left = obj.offsetLeft + 1 + 'px'
}, 30)
}
animate(div,300)
// 动画函数给不同元素记录不同定时器
function animate1(obj, target) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer)
obj.timer = setInterval(function () {
if (obj.offsetLeft >= target) {
// 停止 本质是停止定时器
clearInterval(timer)
}
obj.style.left = obj.offsetLeft + 1 + 'px'
}, 30)
}
animate1(div,300)
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
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
// 缓动效果原理
// 让元素运动速度有所变化,最常见的是让速度慢慢停下来
/*
* 1.让盒子每次移动的距离慢慢变小,速度就会慢慢落下来
* 2.核心算法:(目标值-现在的位置)/ 10 做为每次移动的距离步长
* 3.停止条件是:让当前盒子位置等于目标位置就停止定时器
* 4.注意:步长值需要取整
* */
function animate2(obj, target) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer)
obj.timer = setInterval(function () {
// 步长值写到定时器里面
// 步长值改为整数 不要出现小数的问题
let step = (target - obj.offsetLeft) / 10
// 大于0向上 小于向下
step > 0 ? Math.ceil(step) : Math.floor(step)
if (obj.offsetLeft === target) {
// 停止 本质是停止定时器
clearInterval(timer)
}
// 把每次加1 步长值改为一个慢慢变小的值在
obj.style.left = obj.offsetLeft + step + 'px'
}, 30)
}
// 匀速动画就是盒子当前的位置+固定的值
// 缓动动画就是 盒子当前的位置+变化的值((目标值 - 现在的位置)/10)
// 动画函数添加回调函数
// 函数作为一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行之后,再执行传进去这个函数,这个过程叫做回调
function animate3(obj, target,callback) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer)
obj.timer = setInterval(function () {
// 步长值写到定时器里面
// 步长值改为整数 不要出现小数的问题
let step = (target - obj.offsetLeft) / 10
// 大于0向上 小于向下
step > 0 ? Math.ceil(step) : Math.floor(step)
if (obj.offsetLeft === target) {
// 停止 本质是停止定时器
clearInterval(timer)
// 回调函数写道定时器结束里面
// if(callback){
// // 调用函数
// callback()
// }
callback && callback()
}
// 把每次加1 步长值改为一个慢慢变小的值在
obj.style.left = obj.offsetLeft + step + 'px'
}, 30)
}
btn500.addEventListener('click',function () {
animate3(span,500)
})
btn800.addEventListener('click',function () {
animate3(span,800,function () {
alert('jjj')
})
})
// 动画函数使用
let sliderBar = document.querySelector('.sliderBar')
let con = document.querySelector('.con')
sliderBar.addEventListener('mouseenter', function () {
animate3(con, -160,function () {
// 当我们动画执行完毕,就把 ← 改为 →
sliderBar.children[0].innerHTML = '→'
})
})
sliderBar.addEventListener('mouseleave', function () {
animate3(con, 0,function () {
sliderBar.children[0].innerHTML = '←'
})
})
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
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
// 案例:轮播图
/*
* 轮播图也称为焦点图,是网页中比较常见的网页特效。
* 功能需求:
* ①因为js较多,我们单独新建js文件夹,再新建js文件,引入页面中。
* ②此时需要添加load 事件。
* 1.鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮。
* 2.点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理。
* 3.图片播放的同时,下面小圆圈模块跟随一起变化。
* 4.点击小圆圈,可以播放相应图片。
* 5.鼠标不经过轮播图,轮播图也会自动播放图片。
* 6. 鼠标经过,轮播图模块,自动播放停止。
* */
window.addEventListener('load',function () {
// 1.获取元素
// 按钮
let arrow_l = document.querySelector('.arrow_l')
let arrow_r = document.querySelector('.arrow_r')
// 轮播图模块
let focus = document.querySelector('.focus')
let focusWidth = focus.offsetWidth
// 2.鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮。
focus.addEventListener('mouseenter', function () {
// 首先在css中设为none
arrow_l.style.display = 'block'
arrow_r.style.display = 'block'
clearInterval(timer)
timer = null // 清楚定时器变量
})
focus.addEventListener('mouseenter', function () {
// 首先在css中设为none
arrow_l.style.display = 'none'
arrow_r.style.display = 'none'
timer = setInterval(function () {
// 手动调用点击事件
arrow_r.click()
},2000)
})
// 3.动态生成小圆圆 有几张照片就生成几个
let ul = focus.querySelector('ul')
let ol = focus.querySelector('.circle')
for (let i = 0; i < ul.children.length; i++) {
// 创建一个小li
let li = document.createElement('li')
// 记录当前小圆圈的索引号 通过自定义属性来做
li.setAttribute('index', i)
// 小li插入到ol里面
ol.appendChild(li)
// 4.小圆圈排他思想
/*
* 1.小圆圈的排他思想
* 2.点击当前小圆圈,就添加current类
* 3.其余小圆圈就移除这个current类
* */
li.addEventListener('click', function () {
// 把所有小li 清除 current类名
for (let i = 0; i < ol.children.length; i++) {
ol.children[i].className = ''
}
// 当前的小li 设置current类型
this.className = 'current'
// 5.点击小圆圈滚动图片
/*
* 1.点击小圆圈滚动图片
* 2.此时用到animate动画函数,将JS文件引入
* 3.使用动画函数的前提,该元素必须有定位
* 4.注意是ul移动而不是li
* 5.滚动图片的核心算法:点击某个小圆圈,就让图片滚动 小圆圈的索引号乘以图片的宽度做为ul移动距离
* */
// 当我们点击了某个小li 就拿到当前小li的索引号
let index = this.getAttribute('index')
// 当我们点击了某个小li 就要把这个li的索引号给num
num = index
// 当我们点击了某个小li 就要把这个li的索引号给circle
circle = index
animate3(ul, -index * focusWidth)
})
}
// 把ol里面的第一个小li设置类名为current
ol.children[0].className = 'current'
// 6.克隆第一张图片
/*
* 1.克隆第一张图片
* 2.克隆ul第一个li cloneNode() 加true 深克隆 复制里面的子节点 false 浅克隆
* 3.添加到ul最后面 appendChild
* */
let first = ul.children[0].cloneNode(true)
ul.appendChild(first)
// 7.点击右侧按钮无缝滚动
/*
* 1.点击右侧按钮一次,就让图片滚动一张
* 2.声明一个变量num,点击一次,自增1,就让这个变量乘以图片宽度,就是ul的滚动距离
* 3.图片无缝滚动原理
* 4.把ul第一个li复制一份,放到ul的最后面
* 5.当图片滚动到克隆的最后一张图片时,让ul快读的、不做动画的跳到最左侧:left为0
* 6.同时num赋值为0,可以重新开始滚动图片
* */
let num = 0
// circle控制小圆圈的播放
let circle = 0
let flag = true
arrow_r.addEventListener('click', function () {
if (flag) {
flag = false // 关闭节流阀
// 如果走到了最后复制的一张图片,此时,我们的ul要快速复原left改为0
if (num === ul.children.length - 1) {
ul.style.left = 0
num = 0
}
num++
animate3(ul, -num * focusWidth,function () {
flag = true
})
// 8.点击右侧按钮,小圆圈跟着一起变化,可以再声明一个变量控制小圆圈的播放
/*
* 1.点击右侧按钮,小圆圈跟随变化
* 2.最简单的做法再声明一个变量circle,每次点击自增1,注意,左侧也需要这个变量,因此要声明全局变量
* */
circle++
// 如果circle == 4 说明走到最后我们克隆的这张图片
if (circle === ol.children.length) {
circle = 0
}
circleChange()
}
})
// 9.左侧按钮做法
arrow_l.addEventListener('click',function () {
// 5.1节流阀
// 防止轮播图按钮连续点击造成播放或快
// 目的:当上一个函数动画执行完毕,再去执行下一个函数动画,让事件无法连续触碰
// 核心实现思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数
/*
* 1.开始设置一个变量var flag = true
* 2.if(flag){flag = false;do something} 关闭水龙头
* 3.利用回调函数 动画执行完毕 flag = true 打开水龙头
* */
if(flag){
flag = false
// 如果走到了最后复制的一张图片,此时,我们的ul要快速复原left改为0
if (num === 0) {
num = ul.children.length - 1
ul.style.left = -num * focusWidth + 'px'
}
num--
animate3(ul, -num * focusWidth,function () {
flag = true
})
// 8.点击右侧按钮,小圆圈跟着一起变化,可以再声明一个变量控制小圆圈的播放
/*
* 1.点击右侧按钮,小圆圈跟随变化
* 2.最简单的做法再声明一个变量circle,每次点击自增1,注意,左侧也需要这个变量,因此要声明全局变量
* */
circle--
// 如果circle < 0 说明走到最后我们克隆的这张图片
// if (circle < 0) {
// circle = ol.children.length - 1
// }
circle = circle < 0 ? ol.children.length - 1 : circle
circleChange()
}
})
// 10.自动播放功能
/*
* 1.添加定时器
* 2.自动播放轮播图,实际就类似点点击右侧按钮
* 3.此时我们使用手动调用右侧按钮点击事件arrow_r.click()
* */
let timer = setInterval(function () {
// 手动调用点击事件
arrow_r.click()
},2000)
function circleChange() {
// 先清楚其余小圆圈的current 类名
for (let i = 0; i < ol.children.length; i++) {
ol.children[i].className = ''
}
ol.children[circle].className = 'current'
// 留下当前的小圆圈的current类名
}
})
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
* 案例:筋斗云案例
* 1.鼠标经过某个小li,筋斗云跟着当前小li
* 2.鼠标离开这个小li,筋斗云复原为原来的位置
* 3.鼠标点击了某个小li,筋斗云就会留在点击这个小li的位置
* 4.鼠标离开某个小li,就把目标值设为0
* 5.如果点击了某个小li,就把li当前的位置存储起来,作为筋斗云的起始位置
* */
window.addEventListener('load',function () {
// 1. 获取元素
let cloud = document.querySelector('.cloud')
let c_nav = document.querySelector('.c-nav')
let lis = c_nav.querySelector('li')
// 2. 给所有小li绑定事件
// 这个current作为筋斗云的起始位置
let current = 0
for(let i = 0;i<lis.length;i++){
// (1) 鼠标经过当前小li的位位置作为目标值
lis[i].addEventListener('mouseenter',function () {
animate3(cloud,this.offsetLeft)
})
// (2)鼠标离开就回到起始位置
lis[i].addEventListener('mouseleave',function () {
animate3(cloud,current)
})
// (3) 当我们鼠标点击,就把当前位置作为目标值
lis[i].addEventListener('click',function () {
current = this.offsetLeft
})
}
})
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
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
上次更新: 2024/08/14, 04:14:33