BOM BOM概述 BOM( Browser Object Model )浏览器对象模型,它提供了独立于内容而与浏览器窗口 进行交互的对象,其核心对象是 window
BOM的构成
BOM 比 DOM 更大,它包含 DOM。
window 对象是浏览器的顶级对象,它具有双重角色
它是 JS 访问浏览器窗口的一个接口
它是一个全局对象。定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法
在调用的时候可以省略 window,前面学习的对话框都属于 window 对象方法,如 alert()、prompt()
等。
window对象的常见事件 窗口加载事件 window.onload
是窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像,脚本文件,CSS文件等),就调用的处理函数。
1 2 3 4 5 6 7 window .onload = function ( ) { }; window .addEventListener("load" ,function ( ) {});
有了window.onload
就可以把JS代码写到页面元素的上方
因为onload
是等页面内容全部加载完毕,再去执行处理函数
window.onload
传统注册事件方式,只能写一次,以最后一个为准
如果使用addEventListener 则没有限制
1 document .addEventListener('DOMContentLoaded' ,function ( ) {})
DOMCountentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等
如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间,交互效果就不能实现,必然影响用户的体验,此时用 DOMContentLoaded
事件比较合适。
调整窗口大小事件 window.onresize
是调整窗口大小加载事件,当触发时就调用的处理函数
1 2 3 window .onresize = function ( ) {}window .addEventListener('resize' ,function ( ) {});
只要窗口大小发生像素变化,就会触发这个事件
我们经常利用这个事件完成响应式布局。window.innerWidth
当前屏幕的宽度
定时器 window 对象给我们提供了两个定时器
setTimeout()
setInterval()
setTimeout()定时器 setTimeout()
方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。
1 window .setTimeout(调用函数,[延迟的毫秒数]);
window
可以省略
这个调用函数
可以直接写函数
或者写函数名
或者采取字符串 ‘函数名()’ (不推荐)
延迟的毫秒数省略默认是0,如果写,必须是毫秒
因为定时器可能有很多,所以我们经常给定时器赋值一个标识符
setTimeout()
这个调用函数我们也称为回调函数 callback
普通函数是按照代码顺序直接调用,而这个函数,需要等待事件,事件到了才会去调用这个函数,因此称为回调函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <body> <script > setTimeout (function ( ) { console .log('boom!!!' ); }, 3000 ) function fn ( ) { console .log('boooom!' ); } var timer1 = setTimeout (fn, 3000 ); var timer2 = setTimeout (fn, 5000 ); </script > </body>
clearTimeout()停止定时器 clearTimeout()
方法取消了先前通过调用 setTimeout()
建立的定时器
1 window .clearTimeout(timeoutID)
window
可以省略
里面的参数就是定时器的标识符
setInterval()定时器 setInterval()
方法重复调用一个函数,每隔这个时间,就去调用一次回调函数
clearInterval()停止定时器
clearInterval()
方法取消了先前通过调用 setInterval()
建立的定时器
倒计时效果案例
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 <body> <span class ="hour" > 1</span > <span class ="minute" > 2</span > <span class ="second" > 3</span > <script > var hour = document .querySelector('.hour' ); var minute = document .querySelector('.minute' ); var second = document .querySelector('.second' ); var inputTime = +new Date ('2022-5-1 18:00:00' ); countDown(); setInterval (countDown, 1000 ); function countDown ( ) { var nowTime = +new Date (); var times = (inputTime - nowTime) / 1000 ; var h = parseInt (times / 60 / 60 % 24 ); h = h < 10 ? '0' + h : h; hour.innerHTML = h; var m = parseInt (times / 60 % 60 ); m = m < 10 ? '0' + m : m; minute.innerHTML = m; var s = parseInt (times % 60 ); s = s < 10 ? '0' + s : s; second.innerHTML = s; } </script > </body>
发送短信案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <body> 发送短信: <input type ="text" > <button > 发送</button > <script > var btn = document .querySelector('button' ); var time = 9 ; btn.addEventListener('click' , function ( ) { btn.disabled = true ; var timer = setInterval (function ( ) { if (time == 0 ){ clearInterval (timer); btn.disabled = false ; btn.innerHTML = '发送' ; time = 9 ; }else { btn.innerHTML = '还剩' + time +'秒可以重新发送' ; time--; } }, 1000 ) }) </script > </body >
this指向
this
的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this
到底指向谁
现阶段,我们先了解一下几个this指向
全局作用域或者普通函数中this
指向全局对象window
(注意定时器里面的this指向window )
方法调用中谁调用this
指向谁
构造函数中this
指向实例对象
JS执行机制 JS是单线程 JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为 Javascript 这门脚本语言诞生的使命所致——JavaScript 是为处理页面中用户的交互,以及操作 DOM 而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。 应该先进行添加,之后再删除。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
同步和异步 为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,于是,JS 中出现了同步和异步
同步:前一个任务结束后再执行后一个任务
异步:在做这件事的同时,你还可以去处理其他事情
同步任务 同步任务都在主线程上执行,形成一个 执行栈
异步任务
JS中的异步是通过回调函数实现的
异步任务有以下三种类型
普通事件,如click
,resize
等
资源加载,如load
,error
等
定时器,包括setInterval
,setTimeout
等
异步任务相关回调函数添加到任务队列中
执行过程
先执行执行栈中的同步任务
异步任务由异步进程处理放到任务队列(执行时才放入任务队列)
一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行
由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环( event loop)
location对象 window 对象给我们提供了一个 location
属性用于获取或者设置窗体的url,并且可以解析url。
url 统一资源定位符(uniform resouce locator)是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
url 的一般语法格式为:
1 2 3 protocol://host[:port]/path/[?query]#fragment http://www.itcast.cn/index.html?name=andy&age=18#link
组成
说明
protocol
通信协议 常用的http,ftp,maito等
host
主机(域名) www.itheima.com
port
端口号,可选
path
路径 由零或多个'/'
符号隔开的字符串
query
参数 以键值对的形式,通过&
符号分隔开来
fragment
片段 #
后面内容 常见于链接 锚点
location 对象属性
location对象属性
返回值
location.href
获取或者设置整个URL
location.host
返回主机(域名)www.baidu.com
location.port
返回端口号,如果未写返回空字符串
location.pathname
返回路径
location.search
返回参数
location.hash
返回片段 #后面内容常见于链接 锚点
案例:5s后跳转页面 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <body> <button > 点击</button > <div > </div > <script > var btn = document .querySelector('button' ); var div = document .querySelector('div' ); var timer = 5 ; setInterval (function ( ) { if (timer == 0 ) { location.href = 'http://www.itcast.cn' ; } else { div.innerHTML = '您将在' + timer + '秒钟之后跳转到首页' ; timer--; } }, 1000 ); </script > </body>
获取URL参数 实现登录页面login.html到首页index.html的跳转,表单的提交
login.html
1 2 3 4 5 6 7 <body> <form action ="index.html" > 用户名: <input type ="text" name ="uname" > <input type ="submit" value ="登录" > </form > </body >
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <body> <div > </div > <script > console .log(location.search); var params = location.search.substr(1 ); console .log(params); var arr = params.split('=' ); console .log(arr); var div = document .querySelector('div' ); div.innerHTML = arr[1 ] + '欢迎您' ; </script > </body>
location对象方法
location对象方法
返回值
location.assign()
跟href一样,可以跳转页面(也称为重定向页面),可以后退
location.replace()
替换当前页面,因为不记录历史,所以不能后退页面
location.reload()
重新加载页面,相当于刷新按钮或者 f5 ,如果参数为true 强制刷新 ctrl+f5
navigator对象 navigator 对象包含有关浏览器的信息,它有很多属性
我们常用的是userAgent
,该属性可以返回由客户机发送服务器的user-agent
头部的值
下面代码可以判断用户是用哪个终端打开页面的,如果是用 PC 打开的,我们就跳转到 PC 端的页面,如果是用手机打开的,就跳转到手机端页面
1 2 3 4 5 6 if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i ))) { window .location.href = "" ; } else { window .location.href = "" ; }
history对象 window 对象给我们提供了一个 history 对象,与浏览器历史记录进行交互
该对象包含用户(在浏览器窗口中)访问过的 URL。
history对象方法
作用
back()
可以后退功能
forward()
前进功能
go(参数)
前进后退功能,参数如果是 1 前进1个页面 如果是 -1 后退1个页面
1 2 3 4 5 6 7 8 9 10 11 12 <body> <a href ="list.html" > 点击我去往列表页</a > <button > 前进</button > <script > var btn = document .querySelector('button' ); btn.addEventListener('click' , function ( ) { history.go(1 ); }) </script > </body>
PC端网页特效 元素偏移量offset offset概述 我们使用offset系列相关属性可以动态地得到该元素的位置(偏移)、大小等
获得元素距离带有定位的父元素的偏移量
获得元素自身的大小(宽度高度)
返回的数值都不带单位
offset系列属性
作用
element.offsetParent
返回该元素带有定位的父级元素,如果没有则返回body
element.offsetTop
返回元素带有定位的父元素上方的偏移,如果没有则返回body的偏移
element.offsetLeft
返回元素带有定位的父元素左边的偏移,如果没有则返回body的偏移
element.offsetWidth
返回自身包括padding、边框、内容区的宽度
element.offsetHeight
返回自身包括padding、边框、内容区的宽度
offset和style的区别
offset
style
offset可以得到任意样式表中的样式值
style只能得到行内样式表 的样式值
offset系列获得的数值时没有单位的
style.width获得的是带有单位的字符串
offsetWidth包含padding+border+width
style获得不包含padding和border的值
offsetWidth等属性是只读属性 ,只能获取不能赋值
style.width是可读写属性,可以获取也可以赋值
想要获取元素大小位置,用offset更合适
想要给元素更改值,则使用style
拖拽模态框案例 点击链接,显示登录框和遮罩背景,鼠标在登录框标题位置按下,可以移动登录框
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 <script> var login = document .querySelector('.login' ); var mask = document .querySelector('.login-bg' ); var link = document .querySelector('#link' ); var closeBtn = document .querySelector('#closeBtn' ); var title = document .querySelector('#title' ); link.addEventListener('click' , function ( ) { login.style.display = 'block' ; mask.style.display = 'block' ; }) closeBtn.addEventListener('click' ,function ( ) { login.style.display = 'none' ; mask.style.display = 'none' ; }) title.addEventListener('mousedown' , function (e ) { var x = e.pageX - login.offsetLeft; var y = e.pageY - login.offsetTop; 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); }) }) </script>
放大镜效果
页面结构搭建:在小图片盒子里放入一个遮罩盒子,采取定位方式,再在小盒子里放入一个大的图片盒子,在右边显示,也采用定位的方式,在这大图片盒子里放入大图片
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 window .addEventListener('load' , function ( ) { var preview_img = document .querySelector('.preview_img' ); var mask = document .querySelector('.mask' ); var big = document .querySelector('.big' ); preview_img.addEventListener('mouseover' , function ( ) { mask.style.display = 'block' ; big.style.display = 'block' ; }) preview_img.addEventListener('mouseout' , function ( ) { mask.style.display = 'none' ; big.style.display = 'none' ; }) preview_img.addEventListener('mousemove' , function (e ) { var x = e.pageX - this .offsetLeft; var y = e.pageY - this .offsetTop; var maskX = x - mask.offsetWidth / 2 ; var maskY = y - mask.offsetHeight / 2 ; var maskMax = preview_img.offsetWidth - mask.offsetWidth; if (maskX <= 0 ) { maskX = 0 ; } else if (maskX >= maskMax) { maskX = maskMax; } if (maskY <= 0 ) { maskY = 0 ; } else if (maskY >= maskMax) { maskY = maskMax; } mask.style.left = maskX + 'px' ; mask.style.top = maskY + 'px' ; var bigIMg = document .querySelector('.bigImg' ); var bigMax = bigIMg.offsetWidth - big.offsetWidth; var bigX = maskX * bigMax / maskMax; var bigY = maskY * bigMax / maskMax; bigIMg.style.left = -bigX + 'px' ; bigIMg.style.top = -bigY + 'px' ; }) })
client系列 使用client系列相关属性可以获取元素可视区的相关信息,动态得到该元素的边框大小,元素大小
client系列属性
作用
element.clientTop
返回元素上边框的大小
element.clientLeft
返回元素左边框的大小
element.clientWidth
返回自身包括padding,内容区的宽度,不含边框,返回数值不带单位
element.clientHeight
返回自身包括padding,内容区的高度,不含边框,返回数值不带单位
使用scroll系列的相关属性可以动态的得到该元素的大小,滚动距离
scroll系列属性
作用
element.scrollTop
返回被卷去的上侧距离,返回数值不带单位
element.scrollLeft
返回被卷去的左侧距离,返回数值不带单位
element.scrollWidth
返回自身内容实际的宽度,不含边框,返回数值不带单位
element.scrollHeight
返回自身内容实际的高度,不含边框,返回数值不带单位
固定侧边栏案例
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 <body> <div class ="slider-bar" > <span class ="goBack" > 返回顶部</span > </div > <div class ="header w" > 头部区域</div > <div class ="banner w" > banner区域</div > <div class ="main w" > 主体部分</div > <script > var sliderbar = document .querySelector('.slider-bar' ); var banner = document .querySelector('.banner' ); var bannerTop = banner.offsetTop var sliderbarTop = sliderbar.offsetTop - bannerTop; var main = document .querySelector('.main' ); var goBack = document .querySelector('.goBack' ); var mainTop = main.offsetTop; document .addEventListener('scroll' , function ( ) { if (window .pageYOffset >= bannerTop) { sliderbar.style.position = 'fixed' ; sliderbar.style.top = sliderbarTop + 'px' ; } else { sliderbar.style.position = 'absolute' ; sliderbar.style.top = '300px' ; } if (window .pageYOffset >= mainTop) { goBack.style.display = 'block' ; } else { goBack.style.display = 'none' ; } }) </script > </body>
三大系列总结
三大系列大小对比
作用
element.offsetWidth
返回自身包括padding,边框,内容区的宽度
element.clientWidth
返回自身包括padding,内容区的宽度,不包含边框
element.scrollWidth
返回自身实际的宽度,不包含边框
主要用法
offset系列常用于获取元素位置:offsetLeft offsetTop
client系列常用于获取元素大小: clientWidth clientHeight
scroll系列常用于获取元素滚动距离: scrollTop scrollLeft
获取页面滚动距离通过:window.pageXOffset window.pageYOffset
mouseenter和mouseover的区别 当鼠标移动到元素上时就会触发mouseenter事件,类似mouseover,两者的差别是
动画原理 核心原理:通过定时器setInterval()不断移动盒子位置
1 2 3 4 5 6 7 8 9 <script> var div = document .querySelector('div' ); var timer = setInterval (function ( ) { if (div.offsetLeft >= 300 ){ clearInterval (timer); } div.style.left = div.offsetLeft + 1 + 'px' ; }, 30 ) </script>
简单的动画函数封装 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 <body> <button > 点击purple</button > <div > </div > <span > </span > <script > var div = document .querySelector('div' ); var span = document .querySelector('span' ); var btn = document .querySelector('button' ); 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 ) } btn.addEventListener('click' , function ( ) { animate(span, 200 ); }) animate(div, 300 ); </script > </body>
缓动动画的实现 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 <body> <button class ="btn500" > 点击到500</button > <button class ="btn900" > 点击到900</button > <span > </span > <script > var span = document .querySelector('span' ); var btn500 = document .querySelector('.btn500' ); var btn900 = document .querySelector('.btn900' ); 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); if (callback){ callback(); } } obj.style.left = obj.offsetLeft + step + 'px' ; }, 15 ) } btn500.addEventListener('click' , function ( ) { animate(span, 500 , function ( ) { span.style.backgroundColor = 'skyblue' ; }); }) btn900.addEventListener('click' , function ( ) { animate(span, 900 ); }) </script > </body>
滑动条案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <body> <div class ="sliderbar" > <span > ←</span > <div class ="con" > 问题反馈</div > </div > <script > var sliderbar = document .querySelector('.sliderbar' ); var con = document .querySelector('.con' ); sliderbar.addEventListener('mouseenter' , function ( ) { animate(con, -160 , function ( ) { sliderbar.children[0 ].innerHTML = '→' ; }); }) sliderbar.addEventListener('mouseleave' , function ( ) { animate(con, 0 , function ( ) { sliderbar.children[0 ].innerHTML = '←' ; }); }) </script > </body>
轮播图案例
结构搭建 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 <body> <div class="focus fl"> <!-- 左侧按钮 --> <a href="javascript:;" class="arrow-l"> < </a> <!-- 右侧按钮 --> <a href="javascript:;" class="arrow-r"> > </a> <!-- 核心的滚动区域 --> <ul> <li> <a href="#"><img src="upload/focus.jpg" alt=""></a> </li> <li> <a href="#"><img src="upload/focus1.jpg" alt=""></a> </li> <li> <a href="#"><img src="upload/focus2.jpg" alt=""></a> </li> <li> <a href="#"><img src="upload/focus3.jpg" alt=""></a> </li> </ul> <!-- 小圆圈 --> <ol class="circle"> </ol> </div> </body>
功能需求
当鼠标经过轮播图时,左右按钮显示,离开时隐藏
点击小圆圈可以播放对应的图片
点击右侧按钮,图片向左播放一张,左侧按钮同理
图片播放的同时,小圆圈模块跟随一起变化
鼠标不经过轮播图,会自动播放图片,鼠标经过时,播放停止
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 window .addEventListener('load' , function ( ) { var arrow_l = document .querySelector('.arrow-l' ); var arrow_r = document .querySelector('.arrow-r' ); var focus = document .querySelector('.focus' ); focus.addEventListener('mouseenter' , function ( ) { arrow_l.style.display = 'block' ; arrow_r.style.display = 'block' ; clearInterval (timer); timer = null ; }) focus.addEventListener('mouseleave' , function ( ) { arrow_l.style.display = 'none' ; arrow_r.style.display = 'none' ; timer = setInterval (function ( ) { arrow_r.click(); }, 2000 ); }) var ul = focus.querySelector('ul' ); var ol = focus.querySelector('.circle' ) var focusWidth = focus.offsetWidth; for (var i = 0 ; i < ul.children.length ; i++){ var li = document .createElement('li' ); li.setAttribute('index' , i); li.addEventListener('click' , function ( ) { for (var i = 0 ; i < ol.children.length ; i++){ ol.children[i].className = '' ; } this .className = 'current' ; var index = this .getAttribute('index' ); num = index; circle = index; animate(ul, -index * focusWidth); }) ol.appendChild(li); } ol.children[0 ].className = 'current' ; var first = ul.children[0 ].cloneNode(true ); ul.appendChild(first); var num = 0 ; var circle = 0 ; arrow_r.addEventListener('click' , function ( ) { if (num == ul.children.length - 1 ){ ul.style.left = 0 ; num = 0 ; } num++; animate(ul, -num * focusWidth); circle++; if (circle == ol.children.length){ circle = 0 ; } circleChange(); }) arrow_l.addEventListener('click' , function ( ) { if (num == 0 ){ num = ul.children.length - 1 ; ul.style.left = -num * focusWidth + 'px' ; } num--; animate(ul, -num * focusWidth); circle--; if (circle < 0 ){ circle = ol.children.length - 1 ; } circleChange(); }) function circleChange ( ) { for (var i = 0 ; i < ol.children.length; i++){ ol.children[i].className = '' ; } ol.children[circle].className = 'current' ; } var timer = setInterval (function ( ) { arrow_r.click(); }, 2000 ); })
节流阀 用来防止轮播图按钮连续点击造成播放过快,当上一个函数动画内容执行完毕,再去执行下一个动画函数,让事件无法连续点击
核心思路:利用回调函数,添加一个变量来控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var flag = true ; arrow_r.addEventListener('click' , function ( ) { if (flag){ flag = false ; if (num == ul.children.length - 1 ){ ul.style.left = 0 ; num = 0 ; } num++; animate(ul, -num * focusWidth, function ( ) { false = true ; }); circle++; if (circle == ol.children.length){ circle = 0 ; } circleChange(); } })
带有动画的返回顶部案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 goBack.addEventListener('click' ,function ( ) { animate(0 , 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); if (callback){ callback(); } } window .scroll(0 , window .pageYOffset + step) }, 15 )
筋斗云案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <script src="animate.js" ></script> <script > window .addEventListener('load' , function ( ) { var cloud = document .querySelector('.cloud' ); var c_nav = document .querySelector('.c-nav' ); var lis = c_nav.querySelectorAll('li' ); var current = 0 ; for (var i = 0 ; i < lis.length; i++){ lis[i].addEventListener('mouseenter' , function ( ) { animate(cloud, this .offsetLeft); }) lis[i].addEventListener('mouseleave' , function ( ) { animate(cloud, current); }) lis[i].addEventListener('click' , function ( ) { current = this .offsetLeft; }) } }) </script >