JavaScript - 常见页面效果、本地存储

一、动画

1. 动画的原理

  • 获得盒子当前位置
  • 让盒子在当前位置加上1个移动距离
  • 利用定时器不断重复这个操作
  • 加一个结束定时器的条件
  • 意此元素需要添加定位, 才能使用element.style.left
1
2
3
4
5
6
7
8
var div = document.querySelector('div');
var timer = setInterval(function() {
if (div.offsetLeft >= 400) {
// 停止动画 本质是停止定时器
clearInterval(timer);
}
div.style.left = div.offsetLeft + 1 + 'px';
}, 30);

2. 动画函数的封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 function animate(obj, target) {
var timer = setInterval(function() {
if (obj.offsetLeft >= target) {
// 停止动画 本质是停止定时器
clearInterval(timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';

}, 30);
}

var div = document.querySelector('div');
var span = document.querySelector('span');
// 调用函数
animate(div, 300);
animate(span, 200);

3. 给不同的对象添加不同的定时器

::: details

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
div {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}

span {
position: absolute;
left: 0;
top: 200px;
display: block;
width: 150px;
height: 150px;
background-color: purple;
}
</style>
</head>

<body>
<button>点击夏雨荷才走</button>
<div></div>
<span>夏雨荷</span>
<script>
// var obj = {};
// obj.name = 'andy';
// 简单动画函数封装obj目标对象 target 目标位置
// 给不同的元素指定了不同的定时器
function animate(obj, target) {
// 当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
// 解决方案就是 让我们元素只有一个定时器执行
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
if (obj.offsetLeft >= target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 30);
}

var div = document.querySelector('div');
var span = document.querySelector('span');
var btn = document.querySelector('button');
// 调用函数
animate(div, 300);
btn.addEventListener('click', function() {
animate(span, 200);
})
</script>
</body>

</html>

:::

案例 —- 滑动动画原理

::: details

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
div {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}

span {
position: absolute;
left: 0;
top: 200px;
display: block;
width: 150px;
height: 150px;
background-color: purple;
}
</style>
</head>

<body>
<button>点击夏雨荷才走</button>
<span>夏雨荷</span>
<script>
// 缓动动画函数封装obj目标对象 target 目标位置
// 思路:
// 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
// 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
// 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
function animate(obj, target) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
var step = (target - obj.offsetLeft) / 10;
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';

}, 15);
}
var span = document.querySelector('span');
var btn = document.querySelector('button');

btn.addEventListener('click', function() {
// 调用函数
animate(span, 500);
})
// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
</script>
</body>

</html>

:::

案例 —- 缓动动画(多个值之间移动)

::: details

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
div {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}

span {
position: absolute;
left: 0;
top: 200px;
display: block;
width: 150px;
height: 150px;
background-color: purple;
}
</style>
</head>

<body>
<button class="btn500">点击夏雨荷到500</button>
<button class="btn800">点击夏雨荷到800</button>
<span>夏雨荷</span>
<script>
// 缓动动画函数封装obj目标对象 target 目标位置
// 思路:
// 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
// 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
// 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
function animate(obj, target) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 Math.ceil往上取整 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
// 如果 step 大于0,则往上取整,否则就往下 取整
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';

}, 15);
}
var span = document.querySelector('span');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');

btn500.addEventListener('click', function() {
// 调用函数
animate(span, 500);
})
btn800.addEventListener('click', function() {
// 调用函数
animate(span, 800);
})
// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
</script>
</body>

</html>

:::

案例 —- 缓动动画(回调函数)

::: details

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
div {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}

span {
position: absolute;
left: 0;
top: 200px;
display: block;
width: 150px;
height: 150px;
background-color: purple;
}
</style>
</head>

<body>
<button class="btn500">点击夏雨荷到500</button>
<button class="btn800">点击夏雨荷到800</button>
<span>夏雨荷</span>
<script>
// 缓动动画函数封装obj目标对象 target 目标位置
// 思路:
// 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。
// 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长
// 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()

// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
// 如果 step 大于0,则往上取整,否则就往下 取整
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
if (callback) {
// 调用函数
callback();
}
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';

}, 15);
}
var span = document.querySelector('span');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');

btn500.addEventListener('click', function() {
// 调用函数
animate(span, 500);
})
btn800.addEventListener('click', function() {
// 调用函数
animate(span, 800, function() {
// alert('你好吗');
span.style.backgroundColor = 'red';
});
})
// 匀速动画 就是 盒子是当前的位置 + 固定的值 10
// 缓动动画就是 盒子当前的位置 + 变化的值(目标值 - 现在的位置) / 10)
</script>
</body>

</html>

:::

案例 —- 封装动画函数及引用

::: details

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.sliderbar {
position: fixed;
right: 0;
bottom: 100px;
width: 40px;
height: 40px;
text-align: center;
line-height: 40px;
cursor: pointer;
color: #fff;
}

.con {
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 40px;
background-color: purple;
z-index: -1;
}
</style>
<script src="animate.js"></script>
</head>

<body>
<div class="sliderbar">
<span></span>
<div class="con">问题反馈</div>
</div>

<script>
// 1. 获取元素
var sliderbar = document.querySelector('.sliderbar');
var con = document.querySelector('.con');
// 当我们鼠标经过 sliderbar 就会让 con这个盒子滑动到左侧
// 当我们鼠标离开 sliderbar 就会让 con这个盒子滑动到右侧
sliderbar.addEventListener('mouseenter', function() {
// animate(obj, target, callback);
animate(con, -160, function() {
// 当我们动画执行完毕,就把 ← 改为 →
sliderbar.children[0].innerHTML = '→';
});

})
sliderbar.addEventListener('mouseleave', function() {
// animate(obj, target, callback);
animate(con, 0, function() {
sliderbar.children[0].innerHTML = '←';
});
})
</script>
</body>

</html>

:::

::: details

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
// animate.js

function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()

// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';

}, 15);
}

:::

案例 —- 轮播图


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  <div class="banner">
<div class="left_button banner_button"><a href="javascript:;">&#xe685;</a></div>
<div class="right_button banner_button"><a href="javascript:;">&#xe666;</a></div>
<div class="steta">
<ul>
</ul>
</div>
<div class="img">
<ul>
<li><a href="javascript:"><img src="https://img.pupper.cn/img/202112101605182.jpg"></a></li>
<li><a href="javascript:;"><img src="https://img.pupper.cn/img/202112101605097.jpg"></a></li>
<li><a href="javascript:;"><img src="https://img.pupper.cn/img/202112101605471.jpg"></a></li>
<li><a href="javascript:;"><img src="https://img.pupper.cn/img/202112101606060.jpg"></a></li>
</ul>
</div>
</div>

</code-block>

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
* {
padding: 0;
margin: 0;
}

li {
list-style: none;
}

a {
text-decoration: none;
color: #050505;
}

@font-face {
font-family: 'iconfont';
/* Project id 2303857 */
src: url('//at.alicdn.com/t/font_2303857_w55dl274uko.woff2?t=1640252281330') format('woff2'),
url('//at.alicdn.com/t/font_2303857_w55dl274uko.woff?t=1640252281330') format('woff'),
url('//at.alicdn.com/t/font_2303857_w55dl274uko.ttf?t=1640252281330') format('truetype');
}

.banner {
position: relative;
margin: 50px auto;
border: 1px solid #ccc;
width: 500px;
height: 400px;
overflow: hidden;
}

.banner_button {
display: none;
position: absolute;
font-family: 'iconfont';
top: 50%;
background: rgba(208, 208, 208, 0.5);
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
transform: translate(0, -50%);
}

.left_button {
left: 0px;
}

.right_button {
right: 0px;
}

.steta ul {
position: absolute;
top: 93%;
left: 50%;
transform: translate(-50%, -50%);
height: 30px;
line-height: 30px;
text-align: center;
}

.steta ul li {
float: left;
width: 15px;
height: 15px;
border-radius: 50%;
margin: 0 10px;
border: 1px solid #FFFFFF;
}

.colorr {
background-color: #FFFFFF;
}

.img {
position: absolute;
width: 3000px;
z-index: -1;
}

.img li {
float: left;
width: 500px;
height: 400px;
}

.img img {
width: 100%;
height: 100%;
}

</code-block>

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
var banner = document.querySelector('.banner');
var lb = document.querySelector('.left_button');
var rb = document.querySelector('.right_button');
var img = document.querySelector('.img');
var steta_ul = document.querySelector('.steta').querySelector('ul');

// 图片和小圆点 标识符(以 下标 为参照物)
var num = 0;

// 所有图片
var img_ul = img.querySelector('ul');
// 单个图片的宽度
var img_li_wdith = img_ul.children[0].offsetWidth;

// 鼠标经过 左右按钮显示
banner.addEventListener('mouseenter', function() {
lb.style.display = 'block';
rb.style.display = 'block';
// 清除 自动播放定时器
clearInterval(timer);
timer = null; // 清除定时器变量
})
// 鼠标离开,按钮隐藏
banner.addEventListener('mouseleave', function() {
lb.style.display = 'none';
rb.style.display = 'none';
// 重新添加定时器
timer = setInterval(function () {
// 手动调用 点击事件
rb.click();
}, 2000);
})

// 根据图片数量添加小圆点
for (var i = 0; i < img_ul.children.length; i++) {
// 先创建元素,在添加元素
var li = document.createElement('li');
// 给元素设置自定义属性,记录索引号
li.setAttribute('index', i)
steta_ul.appendChild(li);
// 小圆圈变色
li.addEventListener('click', function(){
// 清除所有小圆圈的颜色
for (var j = 0; j < steta_ul.children.length; j++) {
steta_ul.children[j].className = '';
}
// 给点击的小圆圈变色(增加类)
this.className = 'colorr';

// 点击小圆圈,变更图片
// 获取 点击圆圈的 index 属性
var index = this.getAttribute('index');
// 防止 图片切换错乱
num = index;
// 调用 移动函数
animate(img, -img_li_wdith * index)
})
}
// 默认显示第一个小圆点
steta_ul.children[0].className = 'colorr';

// 克隆 第一个图片 添加到最后,做无缝转换
// 小圆点已添加完成,克隆图片不会影响 小圆点的数量
var clone_li = img_ul.children[0].cloneNode(true);
img.querySelector('ul').appendChild(clone_li);

// 节流阀(防止多次重复点击)
var flag = true;

// 点击 左右按钮,图片移动(根据 num 值判断)
rb.addEventListener('click', function () {
if (flag) {
flag = false; // 关闭节流阀
// 无缝衔接
if (num == img_ul.children.length - 1) {
img.style.left = 0 + 'px';
num = 0;
}
// 根据 num 值 更变图片
num++;
animate(img, -img_li_wdith * num, function () {
flag = true; // 动作完成后,打开节流阀
});
// 小圆点 跟随 图片 变化
circleChange();

}
})

lb.addEventListener('click', function () {
if (flag){
flag = false;
if (num == 0) {
num = img_ul.children.length - 1;
img.style.left = -img_li_wdith * (img_ul.children.length - 1) + 'px';
}
num--;
animate(img, -img_li_wdith * num, function(){
flag = true;
});
// 小圆点 跟随 图片 变化
circleChange();
}
})

// 自动播放轮播图
var timer = setInterval(function (){
// 手动调用 点击事件
rb.click();
},2000)


// 封装 小圆点移动函数
function circleChange() {
// 清除 所有圆点的 样式
for (var j = 0; j < steta_ul.children.length; j++) {
steta_ul.children[j].className = '';
}
// 对 操作的圆点 添加 样式
if (num === img_ul.children.length - 1) {
// 无缝衔接时,改变第一个圆点样式
steta_ul.children[0].className = 'colorr';
} else {
steta_ul.children[num].className = 'colorr';
}
}

// 封装 移动函数
function animate(obj, target, callback) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}

</code-block>

</code-group>

案例 —- 返回页面某个位置

::: details

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
<!DOCTYPE html>
<html>

<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
* {
padding: 0px;
margin: 0px;
}

.demo {
/* position: relative; */
margin: 5px auto;
width: 600px;
}

.handr {
width: 100%;
height: 100px;
background-color: aquamarine;
}

.banner {
width: 100%;
height: 500px;
margin-top: 10px;
background-color: chocolate;
}

.bodyr {
width: 100%;
height: 800px;
margin-top: 10px;
background-color: #00A4FF;
}

.loos {
position: absolute;
right: 35px;
top: 200px;
width: 50px;
height: 100px;
background-color: chartreuse;
}

.loos span {
display: none;
}
</style>
</head>

<body>
<div class="demo">
<div class="handr"></div>
<div class="banner"></div>
<div class="bodyr"></div>
<div class="loos">
<span>返回顶部</span>
</div>
</div>
<script>
var loos = document.querySelector('.loos')
var banner = document.querySelector('.banner')
var bodyr = document.querySelector('.bodyr')
var span = loos.querySelector('span')
// banner 距离页面顶部的高度
var bannertop = banner.offsetTop
// 返回块 停止的位置
var loostop = loos.offsetTop - bannertop
// body 距离页面顶部的高度
var bodyrtop = bodyr.offsetTop;


// 页面滚动事件
document.addEventListener('scroll', function () {
if (window.pageYOffset >= bannertop) {
// 固定定位 是以 浏览器可视区域为参考的
// 绝对定位 是以 有定位的父元素 为参考的
loos.style.position = 'fixed';
loos.style.top = loostop + 'px';
} else {
loos.style.position = 'absolute';
loos.style.top = '200px';
}

if (window.pageYOffset >= bodyrtop) {
span.style.display = 'block'
} else {
span.style.display = 'none'
}
})

span.addEventListener('click', function () {
// window.scroll(0, 0);
animate(window, 0);
})

// 封装 移动函数
function animate(obj, target, callback) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
var step = (target - window.pageYOffset) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (window.pageYOffset == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
window.scroll(0, window.pageYOffset + step);
}, 15);
}
</script>
</body>

</html>

:::

封装 移动函数(上下移动)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 封装 移动函数(上下移动)
function animate(obj, target, callback) {
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function () {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
var step = (target - window.pageYOffset) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (window.pageYOffset == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
window.scroll(0, window.pageYOffset + step);
}, 15);
}

案例 —- 动态导航背景

::: details

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

<!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>
* {
padding: 0;
margin: 0;
}
ul {
list-style: none;
}
a {
text-decoration: none;
color: #333;
}
body {
background-color: black;
}
.demo {
position: relative;
width: 900px;
height: 42px;
margin: 50px auto;
background: #fff url(https://img.pupper.cn/img/202201041615500.png) no-repeat right center;
border-radius: 5px;
}
.cloud {
position: absolute;
top: 0;
left: 0;
width: 83px;
height: 42px;
background: url(https://img.pupper.cn/img/202201041616469.gif) no-repeat;
}
.demo ul {
position: absolute;
}
.demo li {
float: left;
width: 83px;
line-height: 42px;
text-align: center;
}
.demo a {
display: inline-block;
height: 42px;
}

.demo ul li a:hover {
color: #fff;
}
</style>
<script>
window.addEventListener ('load', function(){
var cloud = document.querySelector('.cloud');
var lis = document.querySelector('.demo').querySelectorAll('li');

// span 起始位置
var start = 0;

// 给所有 li 绑定事件
for (var i = 0; i < lis.length; i++){
// 鼠标经过,把当前 li 作为目标值
lis[i].addEventListener('mouseenter', function(){
animate(cloud, this.offsetLeft);
});
// 鼠标离开,把 0 作为目标值
lis[i].addEventListener('mouseleave', function () {
animate(cloud, start);
});
// 鼠标点击,把当前位置作为目标值
lis[i].addEventListener('click', function () {
animate(cloud, this.offsetLeft);
start = this.offsetLeft;
});
}

// 封装 移动函数
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
callback && callback();
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
})
</script>
</head>
<body>
<div class="demo">
<span class="cloud"></span>
<ul>
<li class="current"> <a href="#">首页新闻</a> </li>
<li> <a href="#">师资力量</a> </li>
<li> <a href="#">活动策划</a> </li>
<li> <a href="#">企业文化</a> </li>
<li> <a href="#">招聘信息</a> </li>
<li> <a href="#">公司简介</a> </li>
<li> <a href="#">你是佩奇</a> </li>
<li> <a href="#">啥是乔治</a> </li>
</ul>
</div>
</body>
</html>

:::

二、 本地存储

1. window.sessionStorage

语法:

存储数据:

1
sessionStorage.setItem(key, value)

获取数据:

1
sessionStorage.getItem(key)

删除数据:

1
sessionStorage.removeItem(key);

清空所有数据:

1
sessionStorage.clear();

特点:

  • 生命周期为关闭浏览器窗口
  • 在同一页面下,数据可以共享
  • 以键值对的形式存储
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
<div class="demo">
<input type="text">
<button class="set">存储数据</button>
<button class="get">获取数据</button>
<button class="remove">删除数据</button>
<button class="clear">清空所有数据</button>
</div>
<script>
var inp = document.querySelector('input');
var set = document.querySelector('.set');
var get = document.querySelector('.get');
var rem = document.querySelector('.remove');
var clear = document.querySelector('.clear');

set.addEventListener('click', function () {
var val = inp.value;
sessionStorage.setItem('uname', val);
})
get.addEventListener('click', function () {
inp.value = sessionStorage.getItem('uname')
})

rem.addEventListener('click', function () {
inp.value = sessionStorage.removeItem('uname')
})
clear.addEventListener('click', function () {
inp.value = sessionStorage.clear()
})
</script>

2. window.localStorage

语法:

存储数据:

1
localStorage.setItem(key, value)

获取数据:

1
localStorage.getItem(key)

删除数据:

1
localStorage.removeItem(key);

清空所有数据:

1
localStorage.clear();

特点:

  • 生命周期永久生效,除非手动删除,否则关闭页面也会存在
  • 可以多页面共享(同一浏览器)
  • 以键值对的形式存储使用

案例 —- 记住用户名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div class="demo">
<input type="text" id="uname">
<input type="checkbox" id="setUname">记住用户名
</div>
<script>
var uname = document.querySelector('#uname');
var cb= document.querySelector('#setUname');

// 如果有用户名数据,就显示,复选框勾选
if(localStorage.getItem('uname')){
uname.value = localStorage.getItem('uname');
cb.checked = true;
}

// 根据复选框状态改变,选择保存数据还是删除数据
cb.addEventListener('change', function(){
if(cb.checked){
var val = uname.value;
localStorage.setItem('uname', val);
}else{
localStorage.removeItem('uname');
}
})
</script>