一、Window对象
Window 对象表示浏览器中打开的窗口。
PS:对window对象的属性和方法的引用,可以省略“window”这个前缀。如window.clearInterval(timer)可以写成clearInterval(timer)。
二、定时器的开启与关闭:
1、定时器的开启:
(1)setInterval(code,millisec,lang); //按照指定的周期(以毫秒计)来不停地调用函数或计算表达式。
特点:setInterval() 方 ***不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。所有主要浏览器都支持 setInterval() 方法。
A. 参数code:必需。要调用的函数或要执行的代码串。
B. 参数millisec:必需。周期性执行或调用 code 之间的时间间隔,以毫秒计。
C. 参数lang:可选。 脚本语言可以是:JScript | VBScript | JavaScript
(2)setTimeout(code,millisec,lang); //在指定的毫秒数后调用一次函数或计算表达式。
特点:setTimeout()方法在指定的毫秒数后只执行一次函数。所有主要浏览器都支持 setTimeout() 方法。
A. 参数code:必需。要调用的函数或要执行的JavaScript代码串。
B. 参数millisec:必需。在执行代码前需等待的毫秒数
C. 参数lang:可选。 脚本语言可以是:JScript | VBScript | JavaScript
<script type="text/javascript">
function show() {
alert('a');
}
setInterval(show,1000); //每隔1s执行一次,间隔型
setTimeout(show,1000); //只执行一次,延时型
</script>
2、定时器的关闭:
(1)clearInterval(id_of_setinterval);
//该方法可取消由 setInterval() 设置的 timeout。参数必须是由 setInterval() 返回的 ID 值,所有主要浏览器都支持。
(2)clearTimeout(id_of_settimeout) ;
//该方法可取消由 setTimeout() 方法设置的 timeout。参数必须是由setTimeout()返回的ID值。所有主要浏览器都支持。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>定时器的使用</title>
</head>
<body>
<input type="button" id="open" value="开启">
<input type="button" id="close" value="关闭">
<script type="text/javascript">
var open = document.getElementById('open');
var close = document.getElementById('close');
var timer = null;
open.onclick = function () {
//setInterval()是有返回值的,返回的就是打开的那个定时器
timer = setInterval(function () {
alert('a');
},1000);
};
//关闭定时器时,要指定关闭哪个定时器。把setInterval的返回值作为参数传给clearInterval()就行
close.onclick = function () {
clearInterval(timer);
}
</script>
</body>
</html>
3、定时器的应用:
(1)超酷数码时钟的实现(素材下载:https://www.16sucai.com/2011/03/5571.html)
第一步:对页面进行简单的布局
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>定时器的应用之数码时钟</title>
</head>
<body>
<div>
<span>
<img src="images/0.png" alt="">
<img src="images/0.png" alt="">
:
<img src="images/0.png" alt="">
<img src="images/0.png" alt="">
:
<img src="images/0.png" alt="">
<img src="images/0.png" alt="">
</span>
</div>
</body>
</html>
CSS:
<style type="text/css">
* {
margin: 0 auto;
padding: 0;
}
body {
width: 100%;
background-color: #29033E;
}
div {
width: 520px;
height: 520px;
}
div span{
width: 520px;
height: 520px;
background-image: url(images/bg.png);
background-repeat: no-repeat;
color: #fff;
display: table-cell;
font-size: 50px;
text-align: center;
vertical-align: middle;
left: 50%;
}
</style>
第二步:功能实现
实现思路:A. 使用JavaScript的Date对象里的方法获取当前系统的时间,得到的值的类型是Number;
B. 时间的每个部分都是两位的,但是使用Date对象里的方法获取的时间小于10时是一位的,它不会自动 补零,所以需要封装一个补零的函数addZero(),小于10时,前面补零;
C. 修改图片路径。将获取的时间转为字符串,则此时字符串位数对应了时分秒,也对应了6张图片。我们 只要获取对应的字符串里字符的值,就能使用循环改变图片的路径,也就能显示系统时间了;
D. 在字符串里获取指定位置的字符的方法:stringObject.charAt(index)、stringObject[index]
这两个方法的区别:stringObject[index]不兼容IE8以下的浏览器
E. 使用定时器让时钟自动刷新,动态显示系统时间
<script type="text/javascript">
function addZero(n) {
if (n < 10) {
return '0' + n;
} else {
return '' + n;
}
}
window.onload = function () {
var aImg = document.getElementsByTagName('img');
function tick(){
var oDate = new Date();
var str = addZero(oDate.getHours()) + addZero(oDate.getMinutes()) + addZero(oDate.getSeconds());
for (var i = 0; i < aImg.length; i++) {
aImg[i].src = 'images/' + str.charAt(i) + '.png';
}
}
//tick();
setInterval(tick,1000);
}
</script>
这样写存在一个小bug,那就是每次刷新时,有一瞬间它会显示全零的时刻(即00:00:00)。 这是因为定时器有个特性——定时器被打开后它不会立马执行里面的函数,而是要等到一个周期后(这里的一个周期是1s)才执行。所以定时器里的函数第一次执行的时候,已经是一个周期后的事了。这样就会看到全零的时刻(即00:00:00)了。解决办法是先执行一次定时器里的函数,放在setInterval()方法之前之后都没问题。
<script type="text/javascript">
function addZero(n) {
if (n < 10) {
return '0' + n;
} else {
return '' + n;
}
}
window.onload = function () {
var aImg = document.getElementsByTagName('img');
function tick(){
var oDate = new Date();
var str = addZero(oDate.getHours()) + addZero(oDate.getMinutes()) + addZero(oDate.getSeconds());
for (var i = 0; i < aImg.length; i++) {
aImg[i].src = 'images/' + str.charAt(i) + '.png';
}
}
tick();
setInterval(tick,1000);
}
</script>
(2)延时提示框的实现:
第一步:简单布局
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>定时器的应用之延时提示框</title>
</head>
<body>
<div id="div1">
<div id="head_portrait">
<img src="img/head_portrait.png" alt="">
</div>
<div id="data">
<span>userName</span>
<span>座右铭</span>
<span>sex:man age:16</span>
</div>
</div>
</body>
</html>
CSS:
<style type="text/css">
#div1 {
overflow: hidden;
}
#head_portrait {
float: left;
width:106px;
height: 106px;
border:1px solid #666;
border-radius: 50px 50px;
}
#data {
background-color: #ccc;
display: none;
float: left;
margin-left:50px;
width: 300px;
height: 250px;
text-align: center;
line-height: 80px;
}
#data span {
display: block;
}
</style>
第二步:功能实现
① 鼠标移到头像(head_portrait)上时,资料框(data)显示出来;移出头像时,资料框消失
<script type="text/javascript">
var head_portrait = document.getElementById('head_portrait');
var data = document.getElementById('data');
head_portrait.onmouseover = function () {
data.style.display = 'block';
};
head_portrait.onmouseout = function () {
data.style.display = 'none';
}
</script>
这样操作的话,当鼠标移出头像时,资料框立马会消失。如果想让鼠标移到资料框上,并停留一段时间,可以使用定时器setTimeout();
② 鼠标移出头像时,资料框不会立马消失
head_portrait.onmouseout = function () {
setTimeout(function () {
data.style.display = 'none';
},1000);
}
虽然现在鼠标可以移到资料框上,但过了1秒还是会消失。所以要想它不消失的话,需要关闭这个定时器
③ 鼠标移到资料框上,关闭定时器
var timer = null;
head_portrait.onmouseout = function () {
timer = setTimeout(function () {
data.style.display = 'none';
},1000);
};
data.onmouseover = function () {
clearTimeout(timer);
};
④ 鼠标移出资料框时,资料框要消失
data.onmouseout = function () {
data.style.display = 'none';
}
效果实现了,不过呢还是存在着一个小问题。当我们鼠标移到资料框上时它不会消失,按道理来讲鼠标只要还在这个资料框的范围内资料框就不会消失,也就不会触发onmouseout()事件。可是当我们的鼠标在资料框的范围内来回移动时发现资料框也会消失,这是为什么呢(⊙o⊙)?
原因就是onmouseover()和onmouseout()支持事件冒泡,鼠标经过时自身触发事件,经过其子元素时也触发该事件。当父级元素绑定这两个事件时,子元素也会绑定这两个事件(即父亲有的东西,儿子也有)。而且事件冒泡的特点是事件的触发顺序自内向外,先child后parent。因为我们的资料框里有三个子元素span,所以在资料框内移动鼠标时如果从一个span移到另一个span时,就会触发onmouseout()事件,紧接着父级元素也会触发onmouseout()事件。
解决方法:a. 在data的onmouseover()事件里添加一句data.style.display = 'block';即可。
data.onmouseover = function () {
clearTimeout(timer);
data.style.display = 'block';
};
解决方法:b. 将onmouseover()和onmouseout()改成onmouseenter()和onmouseleave()事件,因为它们不支持事件冒泡。鼠标经过时自身触发事件,经过其子元素时不触发该事件(即父亲有的东西,不归儿子所有)。
head_portrait.onmouseenter = function () {
data.style.display = 'block';
};
head_portrait.onmouseleave = function () {
timer = setTimeout(function () {
data.style.display = 'none';
},1000);
};
data.onmouseenter = function () {
clearTimeout(timer);
// data.style.display = 'block';
};
data.onmouseleave = function () {
data.style.display = 'none';
}
解决完上面的问题后,我们又会发现另一个小bug。编程就是如此,但你解决完一个,另一个又冒出来了,好像bug都解决不完一样。那我们来看看这个问题——当我们的鼠标从资料框移到头像上的过程中,我们会发现资料框会闪一下,其实就是鼠标移出资料框时消失,移到头像时显示出来所造成的现象。
解决的方法:设置定时器,别让鼠标移出资料框时立即消失即可。
⑤ 在资料框的onmouseout()事件里设置定时器,鼠标移出资料框时资料框不会立即消失
data.onmouseout = function () {
timer = setTimeout(function () {
data.style.display = 'none';
},1000);
}
不过这个时候,你又会发现——鼠标移到头像过一会,资料框消失啦/(ㄒoㄒ)/~~,那么这个时候就要关闭定时器了
⑥ 在头像的onmouseover()事件里关闭定时器,资料框就不会消失了。
head_portrait.onmouseover = function () {
clearTimeout(timer);
data.style.display = 'block';
};
⑦ 完整代码:
<script type="text/javascript">
var head_portrait = document.getElementById('head_portrait');
var data = document.getElementById('data');
var timer = null;
head_portrait.onmouseover = function () {
clearTimeout(timer);
data.style.display = 'block';
};
head_portrait.onmouseout = function () {
timer = setTimeout(function () {
data.style.display = 'none';
},1000);
};
data.onmouseover = function () {
clearTimeout(timer);
data.style.display = 'block';
};
data.onmouseout = function () {
timer = setTimeout(function () {
data.style.display = 'none';
},1000);
}
</script>
⑧ 简化后的代码:
<script type="text/javascript">
var head_portrait = document.getElementById('head_portrait');
var data = document.getElementById('data');
var timer = null;
//连等:a = b = 6
head_portrait.onmouseover = data.onmouseover = function () {
clearTimeout(timer);
data.style.display = 'block';
};
head_portrait.onmouseout = data.onmouseout = function () {
timer = setTimeout(function () {
data.style.display = 'none';
},1000);
};
</script>
(3)无缝轮播(素材下载:https://www.16sucai.com/2014/08/47839.html)
第一步:简单布局
HTML:
<div class="banner_content">
<a href="javascript:void(0)" class="left"><</a>
<a href="javascript:void(0)" class="right">></a>
<nav id="banner">
<ul>
<li><img src="img/1.jpg" alt=""></li>
<li><img src="img/2.jpg" alt=""></li>
<li><img src="img/3.jpg" alt=""></li>
<li><img src="img/4.jpg" alt=""></li>
</ul>
</nav>
</div>
CSS:
<style type="text/css">
* {
margin: 0 auto;
padding: 0;
}
.banner_content {
width: 1200px;
overflow: hidden;
}
.banner_content a {
background-color: #99FFFF;
width: 100px;
height: 167px;
text-align: center;
line-height: 167px;
}
.banner_content .left {
float: left;
}
.banner_content .right {
float: right;
}
#banner {
background-color: red;
width: 1000px;
height: 167px;
/*margin:auto;*/
position: relative;
}
/*为ul设置绝对定位的原因是不用一张一张移动li,直接移动ul即可*/
#banner ul {
overflow: hidden;
position: absolute;
left: 0;
top: 0;
}
#banner ul li{
float: left;
list-style-type: none;
width: 250px;
}
#banner ul li img{
width: 100%;
vertical-align: top; /*去除图底部的4px空隙*/
}
</style>
第二步:功能实现:
① 开启定时器
<script type="text/javascript">
window.onload = function () {
var oBanner = document.getElementById('banner');
var oUl = oBanner.getElementsByTagName('ul')[0];
//开启定时器
//element.offsetLeft:返回当前元素的相对水平偏移位置的偏移容器
var timer = setInterval(function () {
oUl.style.left = oUl.offsetLeft - 2 +'px'; //改变ul的left样式的值
},30);
}
</script>
将代码运行,我们发现图片可以向左不断移动。但是随着图片的不断移动,#banner的背景也随着露出来了。因为后
面没有图片遮住它了。该怎么办呢(⊙o⊙)?
轮播应该遵循先进先出的准则。图片向左移动的时候,图片1先进去时则图片1也要先出来,然后接着后面的图片,这样才能够无缝连接
解决方法一:在进行布局的时候,最外层div(或nav)的宽度width应该设为所有图片宽度之和的一半。这样多余的不能够一次性显示出来的图片才会随着已显示出来的图片的移动而紧随其后显示出来。
解决方法二:若在布局的时候,最外层div(或nav)的宽度width等于所有图片宽度之和。则需要对img进行复制,可以使用element.innerHTML(设置或者返回元素的内容)进行复制。我们在JS代码中加入一下代码即可:
② 复制li
//对ul里的li进行复制,处理后是原来li的两倍
oUl.innerHTML = oUl.innerHTML + oUl.innerHTML
不过这时会看到复制的li掉下来了,原因是ul的宽度不够,它的宽度应该等于复制后的所有li的宽度(如果未设置宽度,则是撑起li的img的width)之和。所以我们要为其设置width。
③ 设置复制li后ul的width
var aLi = oUl.getElementsByTagName('li');
//对ul里的li进行复制,处理后是原来li的两倍
oUl.innerHTML = oUl.innerHTML + oUl.innerHTML
//element.offsetWidth:返回元素的宽度,包括边框和填充,但不是边距
oUl.style.width = aLi[0].offsetWidth * aLi.length + 'px';
var aLi = oUl.getElementsByTagName('li');
//对ul里的li进行复制,处理后是原来li的两倍
oUl.innerHTML = oUl.innerHTML + oUl.innerHTML
//element.offsetWidth:返回元素的宽度,包括边框和填充,但不是边距
oUl.style.width = aLi[0].offsetWidth * aLi.length + 'px';
这个时候又还是有一个小bug冒出来了,这图片不断向左移动总会移到尽头的。我们总不能又来复制吧,这可是个大***。我们应该在图片移动到原来的一半时,将它迅速拉回到最开始时的位置。
④ 重置ul的left样式的值为0
//element.offsetLeft:返回当前元素的相对水平偏移位置的偏移容器
var timer = setInterval(function () {
//oUl.offsetWidth前面要加-。oUl.offsetWidth是正值,而图片向左移则oUl.offsetLeft是负值,如果oUl.offsetWidth不加-,oUl.offsetLeft永远都小于它,图片永远待在原地而不会移动
if (oUl.offsetLeft < -oUl.offsetWidth / 2){
oUl.style.left = '0';
}
oUl.style.left = oUl.offsetLeft - 2 +'px';
},30);
当然我们不能让用户看到复制后的图片,只需要在#banner添加overflow:hidden;即可。
⑤ 添加overflow:hidden;
#banner {
background-color: red;
width: 1000px;
height: 167px;
overflow:hidden;
position: relative;
}
⑥鼠标移入图片时,停止轮播,关闭定时器
oBanner.onmouseover = function () {
clearInterval(timer);
};
⑦ 鼠标移出图片时,开始轮播,开启定时器
这里为了减少代码的重写,我们可以提取定时器里的匿名函数并为他命名为move,然后在定时器调用即可。
//element.offsetLeft:返回当前元素的相对水平偏移位置的偏移容器
function move() {
//oUl.offsetWidth前面要加-。oUl.offsetWidth是正值,而图片向左移则oUl.offsetLeft是负值,如果oUl.offsetWidth不加-,oUl.offsetLeft永远都小于它,图片永远待在原地而不会移动
if (oUl.offsetLeft < -oUl.offsetWidth / 2){
oUl.style.left = '0';
}
oUl.style.left = oUl.offsetLeft - 2 +'px';
}
oBanner.onmouseout = function () {
timer = setInterval(move,30);
}
⑧ 点击左边按钮时,图片往左移;点击右边按钮时,图片往右移
首先我们应该知道图片往左移还是右移跟oUl.offsetLeft加的是正数还是负数有关(正数oUl的left值越大,就往右移;负数oUl的left值越小,,就往左移。跟数轴原理一样),跟值的大小无关(大小只是用来决定移动的速度的)。所以我们可以用一个变量speed来存储这个值,通过点击按钮来改变这个变量的值是正数还是负数。
var speed = -2;
function move() {
if (oUl.offsetLeft < -oUl.offsetWidth / 2){
oUl.style.left = '0';
}
oUl.style.left = oUl.offsetLeft + speed +'px';
};
//向左移动
document.getElementsByTagName('a')[0].onclick = function () {
speed = -2;
};
//向右移动
document.getElementsByTagName('a')[1].onclick = function () {
speed = 2;
};
现在点击按钮可以左移右移了,但右移的时候又出现了跟左移移到最后露出背景的情况,所以我们还需要在移动函数move加一个判断。当ul的left值大于0时,它left值要设为ul宽度的一半的相反数。
function move() {
if (oUl.offsetLeft < -oUl.offsetWidth / 2){
oUl.style.left = '0';
} else if (oUl.offsetLeft > 0) {
oUl.style.left = -oUl.offsetWidth / 2 + 'px';
}
oUl.style.left = oUl.offsetLeft + speed +'px';
}
⑨ 完整代码:
<script type="text/javascript">
window.onload = function () {
var oBanner = document.getElementById('banner');
var oUl = oBanner.getElementsByTagName('ul')[0];
var aLi = oUl.getElementsByTagName('li');
var speed = -2;
//对ul里的li进行复制,处理后是原来li的两倍
oUl.innerHTML = oUl.innerHTML + oUl.innerHTML
//element.offsetWidth:返回元素的宽度,包括边框和填充,但不是边距
oUl.style.width = aLi[0].offsetWidth * aLi.length + 'px';
//开启定时器
//element.offsetLeft:返回当前元素的相对水平偏移位置的偏移容器
function move() {
//oUl.offsetWidth前面要加-。oUl.offsetWidth是正值,而图片向左移则oUl.offsetLeft是负值,如果oUl.offsetWidth不加-,oUl.offsetLeft永远都小于它,图片永远待在原地而不会移动
if (oUl.offsetLeft < -oUl.offsetWidth / 2){
oUl.style.left = '0';
} else if (oUl.offsetLeft > 0) {
oUl.style.left = -oUl.offsetWidth / 2 + 'px';
}
oUl.style.left = oUl.offsetLeft + speed +'px';
}
var timer = setInterval(move,30);
oBanner.onmouseover = function () {
clearInterval(timer);
};
oBanner.onmouseout = function () {
timer = setInterval(move,30);
};
//向左移动
document.getElementsByTagName('a')[0].onclick = function () {
speed = -2;
};
//向右移动
document.getElementsByTagName('a')[1].onclick = function () {
speed = 2;
};
}
</script>