[toc]

前端–JavaScript 定时事件 Timing

1. 定时事件入门

JavaScript 可以在时间间隔内执行。这就是所谓的定时事件( Timing Events)。

通过 JavaScript 使用的有两个关键的方法,并且都属于 HTML DOM Window 对象的方法。:

  1. setTimeout(function, milliseconds)在等待指定的毫秒数后执行函数。
  2. setInterval(function, milliseconds)等同于 setTimeout(),但持续重复执行该函数。、
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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>定时器</title>
</head>
<body>
<button>开启单次定时器</button>
<button>关闭单次定时器</button>
<button>开启循环定时器</button>
<button>关闭循环定时器</button>
<script>
var btns = document.getElementsByTagName("button");

function fn() {
console.log("是什么呢?是韭菜苗子呢");
}

var timeout = 0;
btns[0].onclick = function () {
// fn是回调函数,2000是间隔时间单位:毫秒
// 两秒后执行fn()
timeout = setTimeout(fn, 2000);
console.log("timeout = " + timeout);
};
btns[1].onclick = function () {
//清除单次定时任务
clearTimeout(timeout);
console.log("清除单次定时任务完成");
};


var num = 1;
var interval = 0;
btns[2].onclick = function () {
//设置多次定时器
interval = setInterval(function () {
console.log(num++);
}, 1000);
console.log("interval = " + interval);
};

btns[3].onclick = function () {
clearInterval(interval);
console.log("清除多次定时器完成");
}
</script>
</body>
</html>

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
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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>定时器动画</title>
<style>
#box {
width: 160px;
height: 160px;
background-color: #38ff7c;
position: relative;
left: 0px;
top: 0px;
}
</style>
</head>
<body>
<button>开始动画</button>
<button>结束动画</button>
<div id="box"></div>
<script>
var btns = document.getElementsByTagName("button");
var box = document.getElementById("box");

// 第一种方式 解决setInterval多次点击的问题。
// var num=0;
// //记录点击次数
// var count=0;
// var interval=0;
// btns[0].onclick=function(){
// //如果不是第一次点击,直接返回false
// if(count!=0){
// return false;
// }
// interval=setInterval(function(){
// box.style.left=num+"px";
// box.style.top=num+"px";
// num++;
// count++;
// },10)
// };
//
// btns[1].onclick=function(){
// clearInterval(interval);
// //清除定时任务后,让点击次数归零。
// count=0;
// }

//第二种方式,开启定时任务之前,先清理上一次的定时任务

//让box盒子移动的时候用到的自增的值。
var num = 0;
// 定时器的标识
var interval = 0;
//点击开始按钮
btns[0].onclick = function () {
//清理上一次点击留下来的定时任务。方式定时器的累加
clearInterval(interval);
//开启定时任务。
interval = setInterval(function () {
//每隔10ms修改一次box盒子的left大小。
box.style.left = num + "px";
box.style.top = num + "px";
num++;
}, 10)
};
//点击取消按钮,清理定时任务。
btns[1].onclick = function () {
clearInterval(interval);
}
</script>
</body>
</html>

3. 倒计时案例—请仔细阅读协议(5)

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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>倒计时案例</title>
<style>
textarea {
width: 200px;
height: 200px;
}
div {
width: 400px;
height: 500px;
margin: 0 auto 0;
}
button{
width: 200px;
height: 30px;
/*text-align: center;*/
margin-left: 95px;
}
</style>
</head>
<body>
<div>
<h5 style="text-align: center">酒店管理制度</h5>
<div style="border: 1px solid #000000">年满十八周岁,方可入住!</div>
<br/>
<button disabled id="btn">请仔细阅读协议(5)</button>
</div>

<script>
var btn = document.getElementById("btn");
var num = 5;
var flag = setInterval(function () {
num--;
btn.innerText = "请仔细阅读协议(" + num + ")";
if (num == 0) {
clearInterval(flag);
btn.innerText = "同意";
btn.disabled = false;
}
}, 1000)
</script>
</body>
</html>

4. 元素位置的设置

4.1 offset系列
  1. 在没有添加任何定位的情况下,offsetLeft 获取到的是当前盒子左边框与body左边的距离

  2. 父元素相对定位子元素的offsetLeft是相对于父元素。

  3. offset系列: 是一个只读属性,不能赋值。

  4. 偏移量(offset dimension)是javascript中的一个重要的概念。涉及到偏移量的主要是offsetLeft、offsetTop、offsetHeight、offsetWidth这四个属性。

  5. <!DOCTYPE html>
    <html lang="zh-cn">
    <head>
        <meta charset="UTF-8">
        <title>offset系列</title>
        <style>
            *{
                margin:0px;
                padding:0px;
            }
            #box{
                width: 300px;
                height: 300px;
                background-color: #ff0000;
                margin-left:10px;
                border-left:10px solid #000000;
                padding-left:10px;
                position:absolute;
                margin-top:30px;
            }
            #inner{
                width: 100px;
                height: 100px;
                background-color: greenyellow;
                margin-top:30px;
    
                padding-left:10px;
                border-left:10px solid green;
    
                padding-top:20px;
                border-top:20px solid green;
    
            }
        </style>
    </head>
    <body>
    <div id="box">
        <div id="inner"></div>
    </div>
    <script>
        var box = document.getElementById("box");
        var inner= document.getElementById("inner");
        
        // offsetWidth:指的是border(包含border)
        // 以内的盒子的宽度,  == content + padding + border
        var offsetWidth = inner.offsetWidth;
        console.log(offsetWidth);
    
        // offsetHeight:指的是border(包含border)
        // 以内的盒子的高度,  == content + padding + border
        var offsetHeight = inner.offsetHeight;
        console.log(offsetHeight);
    
    </script>
    </body>
    </html>
    
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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>元素的位置设置</title>
<style>
* {
margin: 0;
padding: 0;
}

.box {
width: 200px;
height: 200px;
background-color: #68ff23;
margin-left: 50px;
padding-left: 10px;
/*因为使用定位脱离标准文档流,padding不起作用*/
position: relative;
}

.inner {
width: 100px;
height: 100px;
background-color: #ff272f;

position: absolute;
left: 30px;
margin-left: 30px;
}
</style>
</head>
<body>
<div class="box" id="box">
<div class="inner" id="inner">

</div>
</div>
<script>
var box = document.getElementById("box");
var offsetLeft = box.offsetLeft;
console.log(offsetLeft);//50

var inner = document.getElementById("inner");
var offsetLeft = inner.offsetLeft;
console.log(offsetLeft);//60

</script>
</body>
</html>
动画案例
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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>动画案例</title>
<style>
* {
margin: 0px;
padding: 0px;
}
#box {
position: relative;
width: 100px;
height: 100px;
background-color: #08ff08;
text-align: center;
line-height: 100px;
margin-top: 100px;
}
</style>
</head>
<body>
<button>到400px的位置</button>
<button>到800px的位置</button>
<div id="box">DZSB</div>
<script>
// 移动的盒子对象
var box = document.getElementById("box");

// 按钮
var btns = document.getElementsByTagName("button");

// 点击按钮走到400px的位置
btns[0].onclick = function () {
var timer = setInterval(function () {
// 距离左边的位置
var offsetLeft = box.offsetLeft;
offsetLeft += 9;//这样不会到400px的位置

// 判断盒子距离左边的距离
if (offsetLeft <= 400) {
box.style.left = offsetLeft + "px";
} else {
box.style.left = "400px";
//清除定时器!!!!!!!!!!!!!!
clearInterval(timer);
}
}, 20)
};

btns[1].onclick = function () {
var timer = setInterval(function () {
var offsetLeft = box.offsetLeft;
offsetLeft += 9;//这样不会到400px的位置
if (offsetLeft <= 800) {
box.style.left = offsetLeft + "px";
} else {
box.style.left = "800px";
clearInterval(timer);
}
}, 20)
}
</script>
</body>
</html>
动画案例函数封装
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
<script>
// 按钮
var btns = document.getElementsByTagName("button");

// 移动的盒子对象
var box = document.getElementById("box");

//点击按钮走到400px的位置
btns[0].onclick = function () {
animate(box, 400);
};

//点击按钮走到800px的位置
btns[1].onclick = function () {
animate(box, 800);
};

function animate(obj, target) {
clearInterval(obj.timer);
// obj.timer obj是个对象,动态的添加了已给timer属性,启动定时任务。
obj.timer = setInterval(function () {
// 步长,每次进到定时器中都要 走的歩数
var step = 9;
// 当前的元素对象距离左边的像素。
var current = obj.offsetLeft;
// 如果盒子的当前位置大于 要到达的位置,盒子应该反向移动,
// 所以步长变成负数。
if (current > target) {
step = -9;
}
//Math.abs(target - current) 盒子移动的最大距离
//Math.abs(step) 盒子步长的绝对值
if (Math.abs(target - current) > Math.abs(step)) {
// 如果盒子没走完 ,接着走下一步。
current += step;
// 将盒子当前的位置赋值给盒子。
obj.style.left = current + "px"
} else {
clearInterval(obj.timer);
obj.style.left = target + "px";
}
}, 20)
}
</script>
4.2 scroll系列
  1. box.scrollWidth; 如果单行文本的内容没有超过盒子的宽度,那么scrollWidth指的 是盒子的宽度;如果单行文本超过了盒子的宽度,那么scrollWIdth指的是文本的宽度。
  2. box.scrollHeight;如果单行文本的内容没有超过盒子的高度度,scrollHeight指的 是盒子的高度;如果单行文本超过了盒子的高度,那么scrollHeight指的是文本的高度。
  3. box.scrollTop 指的是滚动条距离上边的距离
  4. box.scrollLeft指的是滚动条距离左边的距离。
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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>scroll系列</title>
<style>
#box {
width: 300px;
height: 300px;
background-color: greenyellow;
/*hidden完全隐藏 auto 自动*/
overflow: auto;
}
</style>
</head>
<body>
<div id="box">
<p>喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵</p>
<p>喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵</p>
<p>喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵</p>
<p>喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵</p>
<p>喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵</p>
<p>喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵</p>
<p>喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵</p>
<p>喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵</p>
<p>喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵</p>
<p>喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵喵</p>

</div>
<script>
var box = document.getElementById("box");

// 如果单行文本的内容没有超过盒子的宽度,那么scrollWidth指的 是盒子的宽度
// 如果单行文本超过了盒子的宽度,那么scrollWIdth指的是文本的宽度。

var scrollWidth = box.scrollWidth;
console.log(scrollWidth);

// 如果单行文本的内容没有超过盒子的高度度,scrollHeight指的 是盒子的高度
// 如果单行文本超过了盒子的高度,那么scrollHeight指的是文本的高度。

var scrollHeight = box.scrollHeight;

console.log(scrollHeight);

box.onscroll = function () {
// scrollTop:指的是滚动条距离上边的距离
console.log(box.scrollTop);

// scrollLeft:指的是滚动条距离左边的距离。
console.log(box.scrollLeft);
}
</script>
</body>
</html>
window.onscroll 事件
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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>scroll系列</title>
<style>
#box {
width: 100%;
height: 100px;
background-color: #ff9b33;
/*hidden完全隐藏 auto 自动*/
/*overflow:auto;*/
/*display:none;*/
position: fixed;
top: 0px;
left: 0px;
}
</style>
</head>
<body>
<div id="box"></div>
<div style="height:2000px;">

</div>
<script>
// widow body html
// window
// document.body
// document.document.Element.
var box = document.getElementById("box");

// 当浏览器有滚动事件的时候,出发以下函数。
window.onscroll = function () {
// var scrollTop=window.scrollLeft||document.body.scrollTop||document.documentElement.scrollTop;
// 调用函数,获取到滚动对象
var obj = scrollObj();
// 获取滚动条到浏览器上面的距离。
console.log(obj.scrollTop);
if (obj.scrollTop < 1000) {
box.style.display = "block";
} else {
box.style.display = "none";
}
};

// 封装浏览器滚动条。并解决兼容性问题。
function scrollObj() {
var scrollTop = window.scrollTop || document.body.scrollTop || document.documentElement.scrollTop;
var scrollLeft = window.scrollLeft || document.body.scrollLeft || document.documentElement.scrollLeft;
// return [scrollLeft,scrollTop]
//返回一个对象,使用更加灵活。
return {"scrollLeft": scrollLeft, "scrollTop": scrollTop};
}
</script>
</body>
</html>
4.3 client系列

client系列:可视区域

  1. clientWidth:自身的宽度 = content + padding
  2. clientHeight:自身的高度 = content + padding
  3. clientLeft:左边框的宽度
  4. clientTop:上边框的宽度
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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>client系列</title>
<style>
#box {
width: 200px;
height: 200px;
background-color: #ff0000;
border-left: 20px solid #ff7381;
padding-left: 20px;
border-top: 10px solid #87d0da;
padding-top: 10px;
}
</style>
</head>
<body>
<button id="btn">按钮</button>
<div id="box">
</div>
<script>
var btn = document.getElementById("btn");
var box = document.getElementById("box");
btn.onclick = function () {
console.log("clientWidth = " + box.clientWidth);//与border无关
console.log("clientHeight = " + box.clientHeight);//与border无关
console.log("clientLeft = " + box.clientLeft);
console.log("clientTop = " + box.clientTop);
}
</script>
</body>
</html>

image-20201107154204205

5. 无缝轮播图—函数封装

所用到的图片点击下载…

5.1 HTML结构
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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>无缝轮播图</title>
<link rel="stylesheet" href="gra.css">

</head>
<body>
<div class="box">
<ul id="list" class="clearfix">
<li><img src="img/01.jpg" alt=""></li>
<li><img src="img/02.jpg" alt=""></li>
<li><img src="img/03.jpg" alt=""></li>
<li><img src="img/04.jpg" alt=""></li>
<li><img src="img/05.jpg" alt=""></li>
</ul>
<ul id="nav" class="clearfix">
<!-- <li class="current">1</li>-->
<!-- <li>2</li>-->
<!-- <li>3</li>-->
<!-- <li>4</li>-->
<!-- <li>5</li>-->
</ul>
<a href="javascript:void(0)" class="lbtn" id="lbtn"></a>
<a href="javascript:void(0)" class="rbtn" id="rbtn"></a>
</div>
<script src="gra.js"></script>
</body>
</html>
5.2 gra.css
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
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

ul, li {
list-style: none;
}

img {
display: block;
}

.box {
position: relative;
width: 900px;
height: 350px;
margin: 100px auto 0;
overflow: hidden;
/* overflow:hidden 越出盒子部分隐藏 */
}

#list {
width: 54000px;
height: 350px;
position: absolute;
left: 0px;
}

#list > li {
float: left;

}

.clearfix:after {
content: "";
display: block;
clear: both;
}

.box > a {
position: absolute;
width: 40px;
height: 100px;
}

.box > .lbtn {
top: 50%;
left: 0px;
margin-top: -50px;
background: url(img/index.png) 0 0 no-repeat;
}

.box > .rbtn {
right: 0px;
top: 50%;
margin-top: -50px;
background: url(img/index.png) -50px 0 no-repeat;
}

#nav {
position: absolute;
right: 0px;
bottom: 10px;

}

#nav > li {
float: left;
width: 22px;
height: 22px;
border-radius: 50%;
border: 1px solid white;
background-color: black;
font-size: 14px;
text-align: center;
line-height: 22px;
margin-right: 10px;
color: gray;
cursor: pointer;
}

#nav > li.current {
border-color: #ce3a2e;
color: #ce3a2e;
}
5.3. gra.js
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
// 点击右边的下一个按钮
var rbtn = document.getElementById("rbtn");
// 点击左边的下一个按钮
var lbtn = document.getElementById("lbtn");

//轮播图图片的集合的父盒子
var list = document.getElementById("list");

// 克隆节点 ,参数true,深克隆:克隆当前节点及其子节点,
// false:浅克隆,克隆当前节点,不包含子节点
var cloneNode = list.firstElementChild.cloneNode(true);
list.appendChild(cloneNode);

var lisLen = list.getElementsByTagName("li").length;
list.style.width = 900 * lisLen + "px";


//小圆圈导航列表父盒子???????????????????????
var nav = document.getElementById("nav");
//lisLen=6因为有一个是克隆出来的
for (let i = 0; i < lisLen - 1; i++) {
var li = document.createElement("li");
li.innerText = i + 1;
if (i === 0) {
li.className = "current";
}
nav.appendChild(li);
}

//小圆圈导航列表
var lis = nav.getElementsByTagName("li");

//下标
var num = 0;
rbtn.onclick = function () {
//每次点击下一页的按钮下标加一
num++;
//当下标大于四的时候让下标归零
if (num > lisLen - 1) {
num = 1;
list.style.left = "0px";
}
//图片移动的函数
animate(list, -900 * num);
//使用排他思想给小圆圈添加样式
circle2();
};


lbtn.onclick = function () {
//每次点击下一页的按钮下标减一
num--;
//当下标大于四的时候让下标归零
if (num < 0) {
num = lisLen - 2;
list.style.left = -(lisLen - 1) * 900 + "px";
}
//图片移动的方法函数
animate(list, -900 * num);

//使用排他思想给小圆圈添加样式
circle2();
};


//第二种
// 给所有的li标签添加一个索引
for (let i = 0; i < lis.length; i++) {
lis[i].index = i;
}
nav.onclick = function (e) {
var target = e.target;
if (target.tagName === "LI") {
num = target.index;
animate(list, -900 * num);
}
circle(target);
};


//封装
function circle2() {
for (let i = 0; i < lis.length; i++) {
lis[i].className = "";
}
lis[num % (lisLen - 1)].className = "current";
}

function circle(target) {
for (let i = 0; i < lis.length; i++) {
lis[i].className = "";
}
target.className = "current";
}


function animate(obj, target) {
clearInterval(obj.timer);
// obj.timer obj是个对象,动态的添加了已给timer属性,启动定时任务。
obj.timer = setInterval(function () {
// 步长,每次进到定时器中都要 走的歩数
var step = 25;
// 当前的元素对象距离左边的像素。
var current = obj.offsetLeft;
// 如果盒子的当前位置大于 要到达的位置,盒子应该反向移动,
// 所以步长变成负数。
if (current > target) {
step = -25;
}
//Math.abs(target - current) 盒子移动的最大距离
//Math.abs(step) 盒子步长的绝对值
if (Math.abs(target - current) > Math.abs(step)) {
// 如果盒子没走完 ,接着走下一步。
current += step;
// 将盒子当前的位置赋值给盒子。
obj.style.left = current + "px"
} else {
clearInterval(obj.timer);
obj.style.left = target + "px";
}
}, 20)
}