一、定时器
1. setInterval()
函数
-
setInterval()
函数可以重复调用一个函数,在每次调用之间具有固定的时间间隔
。setInterval(function () { // 这个函数将自动被以固定间隔时间调用 }, 2000);
- 第一个参数是函数
- 第二个参数是间隔时间,以毫秒为单位,1000毫秒是1秒
-
函数的参数
setInterval()
函数可以接收第3、4……个参数,它们将按顺序传入函数setInterval(function (a, b) {// 形式参数a的值是88,形式参数b的值是66 }, 2000, 88, 66);
- 从第三个参数开始,表示传入函数内的参数
-
具名函数也可以传入setInterval
var a = 0; function fun() { console.log(++a);}setInterval(fun, 1000);
- 具名函数当做第一个参数,注意这里没有圆括号!
-
清除定时器
clearInterval()
函数可以清除一个定时器。// 设置定时器,并且用timer变量接收这个定时器 var timer = setInterval(function () {}, 2000);// 点击按钮时,清除定时器 oBtn.onclick = function () { clearInterval(timer); }
- 用变量
timer
- 清除定时器的时候,要传入定时器变量
- 用变量
二、延时器
1. setTimeout()
函数
setTimeout()
函数可以设置一个延时器,当指定时间到了之后,会执行函数一次,不再重复执行。setTimeout(function () { // 这个函数会在2秒后执行一次 }, 2000);
- 清除延时器
clearTimeout()
函数可以清除延时器,和clearInterval()
非常类似
三、异步语句
-
setInterval()
和setTimeout()
是两个异步语句。 -
异步(asynchronous):不会阻塞CPU继续执行其他语句,当异步完成时,会执行"回调函数"(callback)
setTimeout(function () { console.log('A'); }, 2000); console.log('B');
- 打印:B A
console.log('B');
异步语句不会阻塞程序的正常执行。
-
使用定时器实现动画
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>#box {position: absolute;top: 100px;left: 100px;width: 100px;height: 100px;background-color: orange;}</style> </head><body><button id="btn">开始运动</button><div id="box"></div><script>// 得到元素var btn = document.getElementById('btn');var box = document.getElementById('box');// 全局变量盒子的left值var left = 100;// 按钮监听btn.onclick = function () {var timer = setInterval(function () {// 改变全局变量left += 10;if (left >= 1000) {clearInterval(timer);}// 设置left属性box.style.left = left + 'px';}, 20);};</script> </body></html>
- 使用定时器可以实现动画,利用的就是"视觉暂留"原理。
- 使用定时器实现动画较为不便:
- 不方便根据动画总时间计算步长
- 运动方向要设置正负
- 多种运动进行叠加较为困难(比如一个方形一边移动 一边变为圆形)
-
JS和CSS3结合实现动画
- JavaScript可以利用
CSS3
的transition
属性轻松实现元素动画。 - JS和CSS3结合实现动画规避了定时器制作动画的缺点
- JavaScript可以利用
-
函数节流
- 函数节流:一个函数执行一次后,只有大于设定的执行周期 后才允许执行第二次
- 函数节流非常容易实现,只需要借助setTimeout()延时器
var lock = true;function 需要节流的函数() {// 如果锁是关闭状态,则不执行 if (!lock) return; // 函数核心语句// 关锁 lock = false;// 指定毫秒数后将锁打开 setTimeout(function () { lock = true; }, 2000);}
-
无缝连续滚动特效
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;}.box {width: 1000px;height: 130px;border: 1px solid #000;margin: 50px auto;overflow: hidden;}.box ul {list-style: none;/* 设置大一点,这样li才能浮动 */width: 5000px;position: relative;}.box ul li {float: left;margin-right: 10px;}</style> </head><body><div id="box" class="box"><ul id="list"><li><img src="images/number/0.png" alt=""></li><li><img src="images/number/1.png" alt=""></li><li><img src="images/number/2.png" alt=""></li><li><img src="images/number/3.png" alt=""></li><li><img src="images/number/4.png" alt=""></li><li><img src="images/number/5.png" alt=""></li></ul></div><script>var box = document.getElementById('box');var list = document.getElementById('list');// 复制多一遍所有的lilist.innerHTML += list.innerHTML;// 全局变量,表示当前list的left值var left = 0;// 定时器,全局变量var timer;move();// 动画封装成函数function move() {// 设表先关,防止动画积累clearInterval(timer);timer = setInterval(function () {left -= 4;// 验收if (left <= - 1260) {left = 0;}list.style.left = left + 'px';}, 20);}// 鼠标进入停止定时器box.onmouseenter = function () {clearInterval(timer);};// 鼠标离开继续定时器box.onmouseleave = function () {move();};</script> </body></html>
-
跑马灯轮播图
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>*{margin: 0;padding: 0;}.carousel {width: 650px;height: 360px;border: 1px solid #000;margin: 50px auto;position: relative;overflow: hidden;}.carousel ul {list-style: none;width: 6000px;position: relative;left: 0px;transition: left .5s ease 0s;}.carousel ul li {float: left;}.carousel .leftbtn {position: absolute;left: 20px;top: 50%;margin-top: -25px;width: 50px;height: 50px;background-color: rgb(28, 180, 226);border-radius: 50%;}.carousel .rightbtn {position: absolute;right: 20px;top: 50%;margin-top: -25px;width: 50px;height: 50px;background-color: rgb(28, 180, 226);border-radius: 50%;}</style> </head> <body><div class="carousel"><ul id="list"><li><img src="images/beijing/0.jpg" alt=""></li><li><img src="images/beijing/1.jpg" alt=""></li><li><img src="images/beijing/2.jpg" alt=""></li><li><img src="images/beijing/3.jpg" alt=""></li><li><img src="images/beijing/4.jpg" alt=""></li></ul><a href="javascript:;" class="leftbtn" id="leftbtn"></a><a href="javascript:;" class="rightbtn" id="rightbtn"></a></div><script>// 得到按钮和ul,ul整体进行运动var leftbtn = document.getElementById('leftbtn');var rightbtn = document.getElementById('rightbtn');var list = document.getElementById('list');// 克隆第一张图片var cloneli = list.firstElementChild.cloneNode(true);list.appendChild(cloneli);// 当前ul显示到第几张了,从0开始数var idx = 0;// 节流锁var lock = true;// 右边按钮监听rightbtn.onclick = function () {// 判断锁的状态if (!lock) return; lock = false;// 给list加过渡,为什么要加??css中不是已经加了么??这是因为最后一张图片会把过渡去掉list.style.transition = 'left .5s ease 0s';idx ++;if (idx > 4) {// 设置一个延时器,延时器的功能就是将ul瞬间拉回0的位置,延时器的目的就是让过渡动画结束之后setTimeout(function() {// 取消掉过渡,因为要的是瞬间移动,不是“咕噜”回去list.style.transition = 'none';list.style.left = 0;idx = 0;}, 500);}list.style.left = -idx * 650 + 'px';// 函数节流setTimeout(function() {lock = true; }, 500);}// 左边按钮监听leftbtn.onclick = function () {if (!lock) return;lock = false;// 判断是不是第0张,如果是,就要瞬间用假的替换真的if (idx == 0) {// 取消掉过渡,因为要的是瞬间移动,不是“咕噜”过去list.style.transition = 'none';// 直接瞬间移动到最后的假图片上list.style.left = -5 * 650 + 'px';// 设置一个延时器,这个延时器的延时时间可以是0毫秒,虽然是0毫秒,但是可以让我们过渡先是瞬间取消,然后再加上setTimeout(function() {// 加过渡list.style.transition = 'left .5s ease 0s';// idx改为真正的最后一张idx = 4;list.style.left = -idx * 650 + 'px';}, 0);} else {idx --;list.style.left = -idx * 650 + 'px';}// 函数节流setTimeout(function() {lock = true; }, 500);}</script> </body> </html>
-
呼吸轮播图
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;}.carousel {width: 650px;height: 360px;border: 1px solid #000;margin: 50px auto;position: relative;}.carousel ul {list-style: none;}.carousel ul li {position: absolute;top: 0;left: 0;/* 透明度都是0 */opacity: 0;transition: opacity 1s ease 0s;}/* 只有第一张透明度是1 */.carousel ul li:first-child {opacity: 1;}.carousel .leftbtn {position: absolute;left: 20px;top: 50%;margin-top: -25px;width: 50px;height: 50px;background-color: rgb(28, 180, 226);border-radius: 50%;}.carousel .rightbtn {position: absolute;right: 20px;top: 50%;margin-top: -25px;width: 50px;height: 50px;background-color: rgb(28, 180, 226);border-radius: 50%;}</style> </head><body><div class="carousel"><ul id="list"><li><img src="images/beijing/0.jpg" alt=""></li><li><img src="images/beijing/1.jpg" alt=""></li><li><img src="images/beijing/2.jpg" alt=""></li><li><img src="images/beijing/3.jpg" alt=""></li><li><img src="images/beijing/4.jpg" alt=""></li></ul><a href="javascript:;" class="leftbtn" id="leftbtn"></a><a href="javascript:;" class="rightbtn" id="rightbtn"></a></div><script>// 得到按钮和ul,ul整体进行运动var leftbtn = document.getElementById('leftbtn');var rightbtn = document.getElementById('rightbtn');var list = document.getElementById('list');var lis = list.getElementsByTagName('li');// 当前是第几张图显示var idx = 0;// 节流var lock = true;// 右按钮rightbtn.onclick = function () {// 判断节流if (!lock) return;lock = false;// 还没有改idx,此时的idx这个图片就是老图,老图淡出lis[idx].style.opacity = 0;idx++;if (idx > 4) idx = 0;// 改了idx,此时的idx这个图片就是新图,新图淡入lis[idx].style.opacity = 1;// 动画结束之后,开锁setTimeout(function () {lock = true;}, 1000);}// 左按钮leftbtn.onclick = function () {// 判断节流if (!lock) return;lock = false;// 还没有改idx,此时的idx这个图片就是老图,老图淡出lis[idx].style.opacity = 0;idx--;if (idx < 0) idx = 4;// 改了idx,此时的idx这个图片就是新图,新图淡入lis[idx].style.opacity = 1;// 动画结束之后,开锁setTimeout(function () {lock = true;}, 1000);}</script> </body></html>
重点内容
- 访问元素节点有哪些方法?
- 节点的关系有哪些?
- 常用节点操作有哪些?
- 节点的创建、移除和克隆要如何实现?
- 事件捕获和冒泡是什么?应该如何设置?
- 什么是事件委托?什么时候要用事件委托?
- 使用定时器和CSS3的过度实现动画