javaSprict BOM操作

it2023-11-07  68

-BOM

BOM概述

window对象常见事件

窗口加载事件

window.onload

页面加载事件

​ window.onload 是窗口(页面加载事件),当文档内容完全加载完成会触发该事件(包括图像、脚本文件、css文件等),就调用处理函数。

​ 1.有了window.onload就可以把js代码写到元素页面的上方,因为onload是等页面内容全部加载完毕再去执行处理函数。

​ 2.window.onload 传统注册事件只能写一次,如多有多个就会以最后一个window.onload为准。

​ 3.如果使用addEventListener则没有限制。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> //---------传统注册事件-------------------------------- // window.onload = function (){ // var btn = document.querySelector('button'); // btn.addEventListener('click',function(){ // alert('123') // }) // } // window.onload = function(){ // alert(22) // } // --------------如果使用addEventListener则没有限制。------------------------ // 推荐 window.addEventListener('load', function () { var btn = document.querySelector('button'); btn.addEventListener('click', function () { alert('123') }) }) window.addEventListener('load', function () { alert(22) }) </script> <button>点击</button> </body> </html>

DOMContentLoaded

DOMContentLoaded 事件触发时候,仅当DOM加载完成,不包括样式表、图片、flash等。ie9以上支持。

如果页面图片很多的话,从用户访问到onload触发可能需要较长的时间交互效果就不能实现,必然影响用户体验,此时用DOMContentLoaded 事件比较合适。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> // --------------如果使用addEventListener则没有限制。------------------------ // 推荐 window.addEventListener('load', function () { var btn = document.querySelector('button'); btn.addEventListener('click', function () { alert('123') }) }) window.addEventListener('load', function () { alert(22) }) // -------DOMContentLoaded ----------------- documen.addEventListener('DOMContentLoaded', function () { alert(33); }) </script> <button>点击</button> </body> </html>

比较

load是等页面内容全部加载完毕,包含dom元素 图片 flash css 等

DOMContentLoaded 是DOM加载完毕,不包含图片 flash css 等就可以执行 加载速度比load跟快一些。

调整窗口大小事件

window.onresize = function(){}; window.addEventListener('resize',function(){ })

window.onresize 是调整窗口大小加载事件,当触发时候就调用的处理函数

注意:

只要窗口大小发生改变,就会触发这个事件。

我们职场利用这个事件来完成响应式布局。window.innerWidth 当前屏幕的宽度。

<!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> div { width: 100px; height: 100px; background-color: cornflowerblue; } </style> </head> <body> <div></div> <script> var div = window.document.querySelector('div'); window.addEventListener('resize', function () { console.log('变化了'); console.log(window.innerWidth); if (window.innerWidth <= 800) { div.style.display = 'none'; } else { div.style.display = 'block'; } }) </script> </body> </html>

定时器

window对象提供了两种定时器

setTimeout()setInterval()

setTimeout() 定时器

只调用一次!!!

setTimeout() 方法用于设置一个定时器,该定时器到期后执行调用函数。

setTimeout() 这个函数我们也称为回调函数callback

普通函数是按照代码顺序直接调用。 而这个函数,需要等待时间,时间到了才调用这个函数。

element.onclick = function(){} 或者element.addEventListener(){‘click’,funcion(){}}; 里面的函数也是回调函数。

window.setTimeout(调用函数,[延迟毫秒数]); <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <!-- --> <script> // 这个window在调用时候可以shenglue // 这个延迟时间默认是毫秒,但是可以省略,如果省略默认是0 //第一种写法 setTimeout(function () { alert('已经两秒了') }, 2000) //第二种写法 // 这个调用函数可以直接写函数 还可以 写函数名 function boom() { alert('砰!') } setTimeout(boom, 3000) // 还有一种写法 不提倡 setTimeout('boom()', 4000) // 页面中可能有很多定时器,所以 最好给定时器加标识符(名字) var timer1 = setTimeout(boom, 5000) </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> div { width: 200px; height: 600px; background-color: coral; } </style> </head> <body> <div> 这是广告 </div> <script> var ad = document.querySelector('div'); setTimeout(function () { ad.style.display = 'none'; }, 3000) </script> </body> </html>
清除定时器clearTimeout

停止setTimeout() 定时器

window.clearTimeout(timeoutID) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button>停止定时器</button> <script> var btn = document.querySelector('button'); var timer = setTimeout(function () { console.log('砰') }, 3000) btn.addEventListener('click', function () { clearTimeout(timer) }) </script> </body> </html>

setInterval()定时器

可以一直循环调用!!!

window.setInterval(回调函数,[间隔的毫秒数]);

setInterval() 方法重复调用一个函数,每隔这个事件就去调用一次回调函数。

注意:

window可以省略。这个回调函数可以直接写函数,或者写函数名或者采取字符串’函数名’ 三种形式。间隔毫秒数默认是0,如果写,必须是毫秒,标书每隔多少毫秒就自动调用这个函数。因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> setInterval(function(){ console.log('砰!'); },1000) </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> #box { width: 150px; height: 200px; border: 1px #ccc solid; margin: 100px auto; } #box>div { /* border: 1px #ccc solid; */ margin-top: 120px; width: 150px; height: 40px; } span { display: inline-block; height: 40px; width: 40px; background-color: #32332E; margin-left: 5px; text-align: center; line-height: 40px; color: cornsilk; } </style> </head> <body> <div id="box"> <div> <span class="hour">1</span> <span class="minute">2</span> <span class="second">3</span> </div> </div> <script> // 1.获取元素 // 时分秒的三个小盒子 var hour = document.querySelector('.hour'); var minute = document.querySelector('.minute'); var second = document.querySelector('.second'); var inputTime = +new Date('2020-9-1 00:00:00');//返回用户输入时间的毫秒数 // 先调用一次倒计时函数,防止页面刷新有空白 conutDown() // 开启定时器 setInterval(conutDown, 1000) function conutDown() { var nowTime = +new Date();//返回当前时间的毫秒数 var times = (inputTime - nowTime) / 1000; //times就是剩余时间总的秒数 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> </html>
清除定时器clearInterval
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button class="begin">开始定时器</button> <button class="stop">停止定时器</button> <script> var begin = document.querySelector('.begin'); var stop = document.querySelector('.stop'); // 先定义一个全部变量方便下面使用 null是一个空对象 var timer = null; begin.addEventListener('click', function () { timer = setInterval(function () { console.log('定时器开始工作'); }, 1000) }) stop.addEventListener('click', function () { clearInterval(timer); }) </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> </head> <body> <input type="number"> <button>点击发送短信</button> <script> var input = document.querySelector('input'); var btn = document.querySelector('button'); var time = 5; btn.addEventListener('click', function () { btn.disabled = true; var timer = setInterval(function () { if (time == 0) { // 清除定时器 clearInterval(timer); btn.innerHTML = '点击输入短信' btn.disabled = false; // 清除定时器之后要重新给time赋值 time = 5; } else { btn.innerHTML = '还剩下' + time + '秒' time = time - 1; } }, 1000) }) </script> </body> </html>

js的执行队列

javaScript 最大的特点就是单线程,同一个事件只能做一件事情。

单线程意味着任务需要排队,会导致的问题:如果js执行时间过长,这样会造成渲染不连贯,导致加载阻塞的感觉。

同步和异步

js的执行机制

location对象

window 对象给我们提供了一个location属性 用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为location对象

URL

统一资源定位符(url),是互联网上标准资源的地址。互联网上每个文件都有一个位置的url,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

location对象的属性

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button>点击</button> <script> var btn = document.querySelector('button'); btn.addEventListener('click',function(){ // console.log(window.location.href); // 点击页面跳转 location.href = 'https://www.bilibili.com/' }) </script> </body> </html>

5秒页面跳转案例

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button>点击</button> <div></div> <script> var btn = document.querySelector('button'); var div = document.querySelector('div'); btn.addEventListener('click', function () { // console.log(window.location.href); // 点击页面跳转 location.href = 'https://www.bilibili.com/' }) var time = 5; //先在前面调用一次函数就不会有一秒的空白 conutDown(); setInterval(conutDown, 1000) function conutDown() { if (time == 0) { location.href = 'https://www.bilibili.com/' time = 5; } else { div.innerHTML = '在' + time + '秒后跳转到雄的页面' time-- } } </script> </body> </html>

获取URL参数,数据在不同页面传递

https://www.bilibili.com/video/BV1k4411w7sV?p=93

login界面代码

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="index.html"> 用户名:<input type="text" name="uname"> <input type="submit" value="登陆"> </form> </body> </html>

index界面代码

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div></div> <script> console.log(location.search);// ?uname=1750306016 // 1.去掉? 用 substr('截取的起始位置','截取几个字符') var params = location.search.substr(1); console.log(params); // 2.利用 = 号 把字符串分割为数组 split('=') // 字符替换为数组 split('分隔符') 与join()把数组转化为字符串相反 // split('分隔符') 里面的分隔符取决于 字符串 里面用什么符号隔开 var arr = params.split('='); console.log(arr); // 把数据写入div中 var div = document.querySelector('div'); div.innerHTML = arr[1]+'你好'; </script> </body> </html>

location 对象的方法

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button>点击</button> <script> var btn = document.querySelector('button'); btn.addEventListener('click',function(){ // 可以记录浏览历史 所以可以实现后退功能 // location.assign('https://www.bilibili.com/'); // 不可以记录浏览历史 所以不可以实现后退功能 // location.replace('https://www.bilibili.com/'); // 刷新按钮 location.reload(); }) </script> </body> </html>

navigator对象

​ navigator 对象 包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的 user-agent 头部的值。

​ 下面的前端代码可以判断用户哪个终端打开页面:

代码演示视频

https://www.bilibili.com/video/BV1k4411w7sV?p=95

history 对象

​ window 对象 给我们提供了一个history 对象,与浏览器记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。

前进后退功能类似于下面按钮

var btn = document.querySelector('button'); btn.addEventListener('click',function(){ history.forward(); })

PC端页面特效

元素偏移量offset系列

​ offset 翻译过来就是偏移量,我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小等。

获得元素距离带有定位父元素的位置。获得自身的大小(宽高)。注意:返回的数值都不带单位

<!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> body { margin: 0; padding: 0; } .father { /* 定位 */ position: relative; width: 100px; height: 100px; background-color: coral; margin: 100px; } .son { width: 50px; height: 50px; background-color: cornflowerblue; margin: 40px; } .w { width: 200px; height: 200px; background-color: rgb(76, 223, 142); margin: 0 auto 200px; padding: 20px; border: 2px solid #000; } </style> </head> <body> <div class="father"> <div class="son"></div> <div class="w"></div> </div> <script> var father = document.querySelector('.father') var son = document.querySelector('.son') var w = document.querySelector('.w') // 1.获得元素的偏移量 位置 返回不带单位的数值 console.log(father.offsetTop); console.log(father.offsetLeft); // 它以带有定位的父亲为准 如果没有父亲或者父亲没有定位 则以 body 为准 console.log(son.offsetLeft); // 2.可以得到元素的大小 宽度 和高度 是包含 padding + border + width console.log(w.offsetWidth); console.log(w.offsetHeight); // 3. 返回带有定位的父亲 否则返回的是body console.log(son.offsetParent); //返回父亲 返回的是最近一级的父亲 不管父亲有没有定位 console.log(son.parentNode); </script> </body> </html>

offset与style的区别

<!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{ width: 200px; height: 200px; background-color: rgb(85, 161, 228) } </style> </head> <body> <div class="box"></div> <script> var box = document.querySelector('.box'); console.log(box.offsetWidth); console.log(box.style.width); </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> .box { width: 300px; height: 300px; background-color: burlywood; margin: 100px auto; } </style> </head> <body> <div class="box"></div> <script> // 鼠标在页面的坐标(e.pageX,e.pageY) // 盒子到页面的距离(box.offsetLeft,box.offsetTop) var box = document.querySelector('.box') box.addEventListener('mousemove', function (e) { // console.log(e.pageX) // console.log(e.pageY); // console.log(box.offsetLeft); // console.log(box.offsetTop); var x = e.pageX - this.offsetLeft; var y = e.pageY - this.offsetTop; // console.log(x); // console.log(y); box.innerHTML = 'x的坐标是:'+x+'y的坐标是:'+y; }) </script> </body> </html>

案例:模态框拖拽

有bug未解决 鼠标点击时候模态框会跳开

<style> .con { padding: 200px 0 0 200px; } .box { width: 300px; box-sizing: border-box; position: relative; } .box img { width: 100%; } .mask { display: none; position: absolute; width: 100px; height: 100px; top: 0; left: 0; background-color: yellow; opacity: .5; cursor: move; /* transform: translate(-50%, -50%); */ } .big { display: none; width: 600px; height: 600px; position: absolute; left: 550px; top: 200px; background-color: pink; border: solid 2px black; overflow: hidden; z-index: 999; } .big img { width: 1000px; display: block; position: absolute; top: 0; left: 0; } </style> <div class="con"> <div class="box"> <img src="/js进阶BOM/案例/timg.jpg" alt=""> <!-- 遮挡层 --> <div class="mask"></div> </div> <div class="big"> <img src="/js进阶BOM/案例/timg.jpg" alt="" class="bigimg"> </div> </div> <!-- 案例分析: 1、整个案例可以分为三个功能模块 2、鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开隐藏两个盒子功能 3、黄色的遮挡层跟随鼠标功能 4、移动黄色遮挡层,大图片跟随移动功能 5、获得鼠标在盒子的坐标 6、把数值给遮挡层作为left和top值 7、此时用到鼠标移动事件,但是还是在小图片盒子内移动 8、遮挡层不能超出雄安盒子范围 9、如果小于0,就把坐标设置为0q 10、求大图片的移动距离公式 遮挡层/遮挡层最大移动距离 = 大图片移动距离/大图片最大移动距离 --> <script> window.addEventListener('load', function () { var box = document.querySelector('.box'); var mask = document.querySelector('.mask'); var big = document.querySelector('.big'); // 鼠标经过box时 大盒子 big 和遮挡层 mask 显示 box.addEventListener('mouseover', function () { mask.style.display = 'block'; big.style.display = 'block'; }) box.addEventListener('mouseout', function () { mask.style.display = 'none'; big.style.display = 'none'; }) box.addEventListener('mousemove', function (e) { // 先计算出鼠标在盒子内的坐标 var x = e.pageX - this.offsetLeft; var y = e.pageY - this.offsetTop; // 遮挡层mask距离盒子边框的距离 或者说mask 移动的距离 var maskX = x - mask.offsetWidth / 2; var maskY = y - mask.offsetHeight / 2; // 遮挡层最大移动距离 var maskMax = box.offsetWidth - mask.offsetWidth; var maskMaxY = box.offsetHeight - mask.offsetHeight; // 如果x坐标小于0,就让mask停在0的位置 if (maskX <= 0) { maskX = 0; } else if (maskX >= maskMax) { maskX = maskMax; } // Y坐标 if (maskY <= 0) { maskY = 0; } else if (maskY >= maskMaxY) { maskY = maskMaxY; } mask.style.left = maskX + 'px'; mask.style.top = maskY + 'px'; // 大图 var bigimg = document.querySelector('.bigimg'); // 大图可移动距离等于图片 - (大盒)容器宽度 var bigmax = bigimg.offsetWidth - big.offsetWidth; var bigmaxY = bigimg.offsetHeight - big.offsetHeight; console.log(bigimg.offsetWidth); console.log(bigmax); // 大图的移动距离,根据公式: 遮挡层/遮挡层最大移动距离 = 大图片移动距离/大图片最大移动距离 var bigX = maskX * bigmax / maskMax; var bigY = maskY * bigmaxY / maskMaxY; bigimg.style.left = -bigX + 'px'; bigimg.style.top = -bigY + 'px'; }) }) </script>

案例:仿京东放大镜效果

<style> .con { padding: 200px 0 0 200px; } .box { width: 300px; box-sizing: border-box; position: relative; } .box img { width: 100%; } .mask { display: none; position: absolute; width: 100px; height: 100px; top: 0; left: 0; background-color: yellow; opacity: .5; cursor: move; /* transform: translate(-50%, -50%); */ } .big { display: none; width: 600px; height: 600px; position: absolute; left: 550px; top: 200px; background-color: pink; border: solid 2px black; overflow: hidden; z-index: 999; } .big img { width: 1000px; display: block; position: absolute; top: 0; left: 0; } </style> <div class="con"> <div class="box"> <img src="/js进阶BOM/案例/timg.jpg" alt=""> <!-- 遮挡层 --> <div class="mask"></div> </div> <div class="big"> <img src="/js进阶BOM/案例/timg.jpg" alt="" class="bigimg"> </div> </div> <!-- 案例分析: 1、整个案例可以分为三个功能模块 2、鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开隐藏两个盒子功能 3、黄色的遮挡层跟随鼠标功能 4、移动黄色遮挡层,大图片跟随移动功能 5、获得鼠标在盒子的坐标 6、把数值给遮挡层作为left和top值 7、此时用到鼠标移动事件,但是还是在小图片盒子内移动 8、遮挡层不能超出雄安盒子范围 9、如果小于0,就把坐标设置为0q 10、求大图片的移动距离公式 遮挡层/遮挡层最大移动距离 = 大图片移动距离/大图片最大移动距离 --> <script> window.addEventListener('load', function () { var box = document.querySelector('.box'); var mask = document.querySelector('.mask'); var big = document.querySelector('.big'); // 鼠标经过box时 大盒子 big 和遮挡层 mask 显示 box.addEventListener('mouseover', function () { mask.style.display = 'block'; big.style.display = 'block'; }) box.addEventListener('mouseout', function () { mask.style.display = 'none'; big.style.display = 'none'; }) box.addEventListener('mousemove', function (e) { // 先计算出鼠标在盒子内的坐标 var x = e.pageX - this.offsetLeft; var y = e.pageY - this.offsetTop; // 遮挡层mask距离盒子边框的距离 或者说mask 移动的距离 var maskX = x - mask.offsetWidth / 2; var maskY = y - mask.offsetHeight / 2; // 遮挡层最大移动距离 var maskMax = box.offsetWidth - mask.offsetWidth; var maskMaxY = box.offsetHeight - mask.offsetHeight; // 如果x坐标小于0,就让mask停在0的位置 if (maskX <= 0) { maskX = 0; } else if (maskX >= maskMax) { maskX = maskMax; } // Y坐标 if (maskY <= 0) { maskY = 0; } else if (maskY >= maskMaxY) { maskY = maskMaxY; } mask.style.left = maskX + 'px'; mask.style.top = maskY + 'px'; // 大图 var bigimg = document.querySelector('.bigimg'); // 大图可移动距离等于图片 - (大盒)容器宽度 var bigmax = bigimg.offsetWidth - big.offsetWidth; var bigmaxY = bigimg.offsetHeight - big.offsetHeight; console.log(bigimg.offsetWidth); console.log(bigmax); // 大图的移动距离,根据公式: 遮挡层/遮挡层最大移动距离 = 大图片移动距离/大图片最大移动距离 var bigX = maskX * bigmax / maskMax; var bigY = maskY * bigmaxY / maskMaxY; bigimg.style.left = -bigX + 'px'; bigimg.style.top = -bigY + 'px'; }) }) </script>

元素可视区client系列

我们使用client系列的相关属性来获取元素可视区的相关信息。通过client系列的相关属性可以得改元素的边框大小、元素大小等。

立即执行函数

(function(){})()

​ 主要作用:创建一个独立作用域 避免命名冲突问题

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> // 立即执行函数:需要调用立马能够自己执行的函数。 // 两种写法 // (function(){})(); // // 或者 // (function(){}()); (function (a, b) { console.log(a); console.log(a + b); console.log(2); //第二个小括号可以看做是调用函数 里面可以添加实参 })(1, 3); // 如果有多个立即执行函数中间一定要用分号隔开 // 也可以给函数添加名字 (function sum(a, b) { console.log(a + b); }(2, 3)) // 立即执行函数最大的作用就是 独立创造了一个作用域 里面所有的变量都是局部变量 </script> </body> </html>

元素滚动scroll系列

scroll系列的相关属性可以动态的得到该元素的大小滚动距离

<!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> div{ width: 100px; height: 100px; background-color: brown; overflow: auto; } </style> </head> <body> <div> 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 </div> <script> var div = document.querySelector('div'); div.addEventListener('scroll',function(){ console.log(div.scrollLeft); }) </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> body, html { margin: 0; padding: 0; } .header { width: 95%; height: 300px; background-color: cadetblue; margin: 0px auto } .article { width: 95%; height: 1000px; background-color: rgb(80, 225, 230); margin: 10px auto } .footer { width: 95%; height: 200px; background-color: rgb(24, 137, 141); margin: 10px auto } .aside { position: absolute; width: 40px; height: 100px; background-color: chartreuse; right: 10px; top: 310px; } .aside div { width: 100%; background-color: darkorange; margin: 50px auto; display: none; cursor: pointer; } </style> </head> <body> <div class="header">头部</div> <div class="aside"> <div id="backtop">返回顶部</div> </div> <div class="article">正文</div> <div class="footer">尾部</div> <!-- 案例分析 1.需要页面滚动元素 scroll 因为是页面滚动 所以事件源是document。 2.滚动到某个位置,就是判断页面被卷去的上部值 3.页面被卷去的头部,可以通过window.pageYOffset 获得 去过 被卷去的是左侧 window.pageXOffset 4.注意:元素被卷去的头部是element.scrollTop,如果是页面被卷去的头部则是window.pageYOffset --> <script> // 获取元素 var aside = document.querySelector('.aside'); var backtop = document.querySelector('#backtop') var header = document.querySelector('.header') console.log(header); // 头部的高度 console.log(header.offsetHeight); // 页面滚动事件 document.addEventListener('scroll', function () { // 页面被卷去的头部 console.log(window.pageYOffset); // 3.当我们页面被卷去的头部大于300px 此时侧边栏改为固定定位 if (window.pageYOffset >= header.offsetHeight) { aside.style.position = 'fixed' aside.style.top = 0 + 'px' backtop.style.display = 'block' } else { aside.style.position = 'absolute' aside.style.top = header.offsetHeight + 'px' backtop.style.display = 'none' } }) backtop.addEventListener('click', function () { window.pageYOffset = 0; }) </script> </body> </html>

三大系列总结

他们的主要用法:

1.offset系列经常用于获取元素位置 offsetLeft offsetTop

2.client经常用于获取元素大小 clientWidth clientHight

3.scroll经常用于获取滚动距离 scrollTop scrollLeft

4.注意页面的滚动距离通过window.pageXOffset 获得

动画原理

核心原理:通过定时器()不断移动盒子位置。

实现步骤:

获得盒子当前的位置让盒子在当前位加上1和移动距离利用定时器不断重复这个动作加一个结束定时器的条件。注意元素需要添加定位,才能使用element.style.left

动画函数封装

注意函数需要传递的两个参数,动画对象和移动的距离。

动画函数给不同元素记录定时器

如果多个元素都使用这个动画效果,每次都要声明一个定时器,我们可以给不同的元素使用不同的定时器(自己专门使用自己的定时器)。

核心原理:利用js是一门动态语言,可以很方便的给当前对象添加属性。

<!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> div { position: absolute; left: 0; width: 200px; height: 200px; background-color: blueviolet; } span { position: absolute; left: 0; width: 100px; height: 100px; background-color: rgb(83, 155, 113); } button { margin-top: 300px; } </style> </head> <body> <div></div> <span></span> <button>点击方块移动</button> <!-- 动画原理 1. 获得盒子当前的位置 2. 让盒子在当前位加上1和移动距离 3. 利用定时器不断重复这个动作 4. 加一个结束定时器的条件。 5. 注意元素需要添加定位,才能使用element.style.left --> <script> // 简单动画函数的封装 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'; }, 1) } var div = document.querySelector('div'); var span = document.querySelector('span') // 调用函数 var button = document.querySelector('button'); // 当我们不断点击了按钮,这个元素的速度会越来越快,因为开启了太多的定时器 // 解决方案就是让元素只有一个定时器执行 button.addEventListener('click', function () { animate(div, 200) animate(span, 600) }) </script> </body> </html>

缓动动画原理

缓动动画就是让元素的运动速度有所变化。

思路:

让盒子每次移动的距离慢慢变小,速度就会慢慢落下来核心算法:(目标值 - 现在的值)/ 10 作为每次移动距离步长停止的条件是:让当前盒子位置等于目标位置就停止定时器步长值需要取整

后退有点bug

<!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> div { position: absolute; left: 0; width: 200px; height: 200px; background-color: blueviolet; } span { position: absolute; left: 0; width: 100px; height: 100px; background-color: rgb(83, 155, 113); } button { margin-top: 300px; } </style> </head> <body> <div></div> <span></span> <button class="button600">点击方块移动600</button> <button class="button1000">点击方块移动1000</button> <script> // 简单动画函数的封装 obj目标函数 target目标对象 function animate(obj, target) { // 解决方案就是让元素只有一个定时器执行 // 先清除以前的定时器只保留一个定时器执行 clearInterval(obj.timer) //↓↓↓↓↓ 给不同元素指定了不同的定时器 obj.timer = setInterval(function () { // 步长值写到定时器里面 // 把步长值改为整数不要出现小数的距离 // var step = Math.ceil((target - obj.offsetLeft) / 10); // 判断div是前进还是后退 时候 步长值是向上取整还是向下取整 var step = (target - obj.offsetLeft) / 10; step = step > 0 ? Math.ceil(step) : Math.floor(step) if (obj.offsetLeft >= target) { // 停止动画本质是停止定时器 clearInterval(obj.timer) } // obj.style.left = obj.offsetLeft + step + 'px'; }, 15) } var div = document.querySelector('div'); var span = document.querySelector('span') // 调用函数 var btn600 = document.querySelector('.button600'); var btn1000 = document.querySelector('.button1000'); // 当我们不断点击了按钮,这个元素的速度会越来越快,因为开启了太多的定时器 // 解决方案就是让元素只有一个定时器执行 btn600.addEventListener('click', function () { animate(div, 200) }) btn1000.addEventListener('click', function () { animate(div, 600) }) </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> div { position: absolute; left: 0; width: 200px; height: 200px; background-color: blueviolet; } button { margin-top: 300px; } </style> </head> <body> <div></div> <button class="button600">点击方块移动600</button> <button class="button1000">点击方块移动1000</button> <script> 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) } var div = document.querySelector('div'); var span = document.querySelector('span') // 调用函数 var btn600 = document.querySelector('.button600'); var btn1000 = document.querySelector('.button1000'); // 当我们不断点击了按钮,这个元素的速度会越来越快,因为开启了太多的定时器 // 解决方案就是让元素只有一个定时器执行 btn600.addEventListener('click', function () { // 回调函数 animate(div, 200, function () { div.style.backgroundColor = 'pink'; }) }) btn1000.addEventListener('click', function () { animate(div, 600) }) </script> </body> </html>

动画函数封装到单独js文件里面

独立新建一个js文件。

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> div { position: absolute; left: 0; width: 200px; height: 200px; background-color: blueviolet; } </style> <script src="/js进阶BOM/js/animate.js"></script> </head> <body> <div></div> <script> var div = document.querySelector('div'); div.addEventListener('click', function () { animate(div, 400); }) </script> </body> </html>

js文件

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) }

mouseenter和mouseover的区别

mouseenter鼠标事件

当鼠标移动到元素上时就会触发mouseenter事件类似于mouseover,他们两者之间的差别是mouseover 鼠标经过自身盒子会触发,经过子级盒子还会触发。mouseenter 只会经过自身盒子触发。之所以这样是因为mouseenter不会冒泡。跟mouseenter搭配的鼠标离开事件mouseleave同样不会冒泡

常见网页特效案例

div.style.backgroundColor = 'pink'; }) }) btn1000.addEventListener('click', function () { animate(div, 600) }) </script> ```

动画函数封装到单独js文件里面

独立新建一个js文件。

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> div { position: absolute; left: 0; width: 200px; height: 200px; background-color: blueviolet; } </style> <script src="/js进阶BOM/js/animate.js"></script> </head> <body> <div></div> <script> var div = document.querySelector('div'); div.addEventListener('click', function () { animate(div, 400); }) </script> </body> </html>

js文件

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) }

mouseenter和mouseover的区别

mouseenter鼠标事件

当鼠标移动到元素上时就会触发mouseenter事件类似于mouseover,他们两者之间的差别是mouseover 鼠标经过自身盒子会触发,经过子级盒子还会触发。mouseenter 只会经过自身盒子触发。之所以这样是因为mouseenter不会冒泡。跟mouseenter搭配的鼠标离开事件mouseleave同样不会冒泡

常见网页特效案例

网页轮播图

最新回复(0)