0
点赞
收藏
分享

微信扫一扫

Javascript(笔记31) - BOM基本操作

Javascript(笔记31) - BOM基本操作


滚动条的滚动距离

浏览器之间的兼容性比较混乱

封装兼容性方法:求滚动轮滚动离getScrollOffset()

window.pageXOffset  /  window.pageYOffset

这两个是 window 上的属性,就是用来求滚动条滚动距离的;IE9以上能用;

当页面没有滚动条,或有滚动条但没滚动的时候:这两值都为0;

window.pageXOffset = 0; 
window.pageYOffset = 0;

先做个有纵向滚动条的页面: 生成100个 <br> ;

让滚动条向下滚动时,观察 window.pageYOffset :

Javascript(笔记31) - BOM基本操作_BOM

此时屏幕最底端距离网页的顶端是多少? 是首屏高度 + 滚动条向下滚动的200PX 

横向滚动条距离与纵向的类似;

封装兼容性函数:getScrollOffset

IE8及以下浏览器的兼容

document.body.scrollLeft  和 window.pageXOffset 等价;

document.body.scrollTop  和 window.pageYOffset 等价;

document.documentElement.scrollLeft 和 window.pageXOffset 等价;

document.documentElement.scrollTop 和 window.pageYOffset 等价;

但是 IE678 下,不确定上面的两个方法哪个好使;但有个特点是:

document.body.scrollLeft 管用的时候,document.documentElement.scrollLeft 就为0;

或者:

document.documentElement.scrollLeft  管用的时候 ,document.body.scrollLeft 就为0;

所以:

把他俩相加,就可以解决IE678的兼容性问题了;

document.body.scrollLeft + document.documentElement.scrollLeft  和 window.pageXOffset 等价;

document.body.scrollTop + document.documentElement.scrollTop  和 window.pageYOffset 等价;


写个兼容方法:

function getScrollOffset(){
if(window.pageXOffset){ // 可以 if(0 && window.pageXOffset) 来跳过 if 调试 else代码
return{
x: window.pageXOffset,
Y: window.pageYOffset
}
}else{
return{
x: document.body.scrollLeft + document.documentElement.scrollLeft,
y: document.body.scrollTop + document.documentElement.scrollTop
}
}
}

试一下:

Javascript(笔记31) - BOM基本操作_javascript_02

这种兼容性的方法,可以存到一个 工具库,用的时候引入就可以了;


查看视口尺寸

求可视区窗口尺寸

封装兼容性方法:求滚动轮滚动离getViewportOffset()

window.innerWidth / window.innerHeight

什么是可视区窗口?

就是在浏览器中(不包括浏览器菜单栏、工具栏等),我们编写HTML文档的部分,改变浏览器大小(拉伸或缩小),也就改变了可视区窗口大小;

用这两个属性看看当前的可视区尺寸:

window.innerWidth: 383;   window.innerHeight : 486

Javascript(笔记31) - BOM基本操作_javascript_03

改变一下浏览器的尺寸现看看:

window.innerWidth: 553; window.innerHeight:545;

Javascript(笔记31) - BOM基本操作_BOM_04


模拟手机尺寸打开,模拟 iphone XR 的尺寸:414*896

window.innerWidth : 414 ; window.innerHeight:896    正好与模拟尺寸一样;

Javascript(笔记31) - BOM基本操作_BOM_05

封装兼容性函数:getViewportOffset

IE8及以下不兼容

什么是标准模式? 是指文档最上面的申明:“<!DOCTYPE html>” 


有这个标准模式;没有声明这个就是怪异模式;

标准模式以下用:

document.documentElement.clientWidth

document.documentElement.clintHeight

怪异模式以下用:

document.body.clientWidth

document.body.clientHeight

其中用来区分标准模式和怪异模式的方法是:document.compatMode 

在标准模式下的返回值是:'CSS1Compat'

在怪异模式下的返回值是:'BackCompat'

封装一个兼容函数: getViewportOffset

function getViewportOffset() {
if (window.innerWidth) {
return {
w: window.innerWidth,
h: window.innerHeight
}
} else {
if (document.compatMode === "BackCompat") {
return {
w:document.body.clientWidth,
h:document.body.clientHeight
}
}else{
return{
w:document.documentElement.clientWidth,
h:document.documentElement.clientHeight
}
}
}
}

试一下:

Javascript(笔记31) - BOM基本操作_javascript_06

查看元素的几何尺寸

domEle.getBoundingClientRect()

该方法返回一个对象,对象里面有 left,top,right,bottom 等属性;

left 和 top 代表该元素左上角的 X 和 Y 坐标;

right 和 bottom 代表元素右下角的 X 和 Y 坐标;

兼容性很好,height 和 width 属性老版本IE并未实现;

返回的结果并不是“实时的”,因为用的不多;

通过这个方法,可以把 DOM 元素在页面里的一些信息返回给我们;

先写个div

<div style="width:100px;height:100px;background-color:red;position:absolute;left:100px;top:100px;"></div>

JS里把这个 div 取出来;

var div = document.getElementsByTagName('div')[0];

看控制台输出:

Javascript(笔记31) - BOM基本操作_javascript_07

有:top,right,bottom,left 的位置,还有width,height;

但这个方法获取的元素的信息不是实时的;

意思是:改变了元素的信息,但这个方法获取的信息不变;

查看元素尺寸

查看元素的宽和高;

这个方法可以取代上面  getBoundingClientReat 方法

dom.offsetWidth  / dom.offsetHeight

用来查看当前元素的宽度和高度;

还是这个div:

<div style="width:100px;height:100px;background-color:red;position:absolute;left:100px;top:100px;"></div>

取出这个div:

var div = document.getElementsByTagName('div')[0];

看控制台:

Javascript(笔记31) - BOM基本操作_BOM_08

给这个div 再个 padding:100px;

/* css */
div{
padding: 100px;
width: 100px;
height: 100px;
background-color: #f00;
position: absolute;
left: 100px;
top: 100px;
}
<!--html-->
<div></div>

再看控制台:

Javascript(笔记31) - BOM基本操作_javascript_09


查看元素位置

查看元素相对文档的坐标;

dom.offsetLeft  / dom.offsetTop

对于无定位父级的元素,返回相对文档的坐标;

对于有定位的父级元素,返回相对于最近的有定位的父级的坐标;

还以上面的 div 为例,看控制台输出:

Javascript(笔记31) - BOM基本操作_javascript_10

当前 div 是相对 body 定位的,所以会返回相对于 body  的坐标;

现在我们改个HTML结构,让里面的 div 相对于外面的 div 定位,看来看一下返回结果:

<style>
div.wrap {
width: 300px; height: 300px;
border: 2px solid #f30;
position: relative; top: 100px; left: 100px;
}
div.demo {
width: 100px; height: 100px;
background-color: #f00;
position: absolute; left: 100px; top: 100px;
}
</style>

<div class="wrap">
<div class="demo"></div>
</div>

效果图:

Javascript(笔记31) - BOM基本操作_javascript_11

取里面那个div.demo : 

var div = document.getElementsByClassName('demo')[0];

控制台输出:

Javascript(笔记31) - BOM基本操作_BOM_12

当相对于外层 div 定位时,返回的结果是相对于定位的父级元素的坐标;

如果我们把里面  div 的定位去掉,改成 margin 的方式,控制台输出不变;

div.demo {
width: 100px; height: 100px;
background-color: #f00;
/* position: absolute; left: 100px; top: 100px; */
margin:100px 0 0 100px;
}

总结:当前元素有无定位并没关系,只要父级元素有定位,就会返回相对于最近的有定位父级的坐标;

所谓无定位的父级就是指:父级的 position:static; 取的默认值,默认值就是无定位;

那么,要想知道最近有定位的父级怎么弄? 


dom.offsetParent

返回最近的有定位的父级,如果没有,就返回 body;   body.offsetParent 返回 null; 

正好有个可用的方法,可以获得当前元素最近无定位的父级,试一下吧:

Javascript(笔记31) - BOM基本操作_BOM_13

如果把 div.wrap 的定位去掉,再看:

Javascript(笔记31) - BOM基本操作_javascript_14

这个方法,可以帮助我们在调试时候确定父级有无定位;


练习:getElementPosition

求元素相对于文档的坐标  getElementPosition 



让滚动条滚动

这三个都是 window 的方法,调用的时候就: window.scroll()

scroll() / scrollTo() / scrollBy()

scroll 和 scrollTo 两个方法效果一样;用法都是将 (x,y) 坐标传入,实现让滚动轮滚动到当前位置;

scrollBy 也是将 (x,y) 坐标传入,重复执行,可以在之前位置基础上累加;

先看 scroll() 和 scrollTo(): 填两参数,第一个是 X 坐标,第二个是 Y坐标;

看控制台:

Javascript(笔记31) - BOM基本操作_javascript_15

滚动屏幕的话,一般没有横向滚动条,所以 X 横向坐标为 0 ;纵向的 Y 纵坐标为 100,会让滚动条向下滚动 100PX;执行一次后,滚动条即向下滚动一次,重复执行无效;

scrollTo() 用法跟 scroll 一样;

scrollBy() 有点不同,填的参数是累加滚动值;意思是执行一次,就向下滚动 100,再执行一次,还会向下滚动100,直到滚不动为止;参数值可为负数,就是每执行一次,向上滚动100;

Javascript(笔记31) - BOM基本操作_javascript_16

结合上面方法,做个练习

练习:快速阅读的功能

分析:一个长页面,在右侧放两个按钮,上面按钮点一下,让页面自动滚动起来;下面按钮点一下,让页面停止滚动;

先写个HTML:

<style>
div.btn {
width: 60px;
height: 60px;
border-radius: 50%;
background-color: rgb(54, 201, 227);
position: fixed;
bottom: 200px;
right: 30px;
text-align: center;
line-height: 60px;
font-size: 20px;
font-weight: bold;
color: #fff;
cursor: pointer;
opacity: 0.9;
}

div.stop {
bottom: 120px;
}
</style>
<div>... ... 大段文字,形成滚动条</div>
<div class="btn scroll">滚动</div>
<div class="btn stop">停止</div>

看下效果:

Javascript(笔记31) - BOM基本操作_javascript_17

现在要做的是给两个按钮加上点击事件,一个让页面滚动起来,一个停止滚动;

JS部分:

var btnScroll = document.getElementsByClassName('scroll')[0];
var btnStop = document.getElementsByClassName('stop')[0];
var flag = true; // 开关锁;
var timer = 0; // 定时器;
btnScroll.onclick = function () {
if (flag) {
timer = setInterval(function () {
window.scrollBy(0, 1); // 页面滚动的距离,越小越平滑;
}, 20); // 时间间隔,越小,滚动就越快;
flag = false;
}
}
btnStop.onclick = function () {
clearInterval(timer);
flag = true;
}


脚本化CSS

可读写“行间样式”,没有兼容性问题,碰到保留字属性,前面应加 css;如:float --> cssFloat

复合属性必须拆解,组合单词变成小驼峰式写法;

写入的值必须是字符串格式;

dom.style.prop

DOM 是不能直接操作CSS的,只能间接的操作;

先建个小方块:

<div style="width:100px;height:100px;background-color:red"></div>

JS把div选出来: 

var div = document.getElementsByTagName('div')[0];

看下控制台:

Javascript(笔记31) - BOM基本操作_BOM_18

间接操作CSS,就是使用 div.style 提供的各种方法和属性了;CSSStyleDeclartion 就是样式表声明,div.style 已经把当前元素能用的样式全展示出来了。展开后可以看到 N 多属性和方法,也可以看到 "012" 的编号和 length 属性,其实是个类数组;类数组也是对象,就可以读写属性;

先试一个:

Javascript(笔记31) - BOM基本操作_javascript_19

使用 div.style 可以读写 div 的宽;注意:写入的属性值都必须是字符串形式

再试几个:

Javascript(笔记31) - BOM基本操作_javascript_20

注意:CSS属性里连接符“-”在这里是不能用的,要改成小驼峰式的命名

再来:

Javascript(笔记31) - BOM基本操作_BOM_21

行内样式里,并没有定义 border-radius ,也可以通过 div.style 进行修改;

我们在 style 里给 div 加点样式: 

<style>
div{border:5px solid #000; width:500px;}
</style>

看下效果:

Javascript(笔记31) - BOM基本操作_BOM_22

看下控制台:

Javascript(笔记31) - BOM基本操作_BOM_23

div 的 border 样式会生效;但行内样式的优先级高,div 的 width 样式并不生效;

那么在 div.style 能不能获取到这个 border 呢? 看控制台:

Javascript(笔记31) - BOM基本操作_javascript_24

div.style 里虽然没有读到 border ,但可以写入新的样式:

Javascript(笔记31) - BOM基本操作_BOM_25

以前的版本不让这样写,只能写成 borderWidth = "10px" , borderStyle = "dotted" 这样,拆解开,现在可以这样写了;看下效果:

Javascript(笔记31) - BOM基本操作_javascript_26

我们成功写入行内样式,并生效;

面对保留字,其实也是可以的,但最好使用规范里,加上 css 并以小驼峰命名:

Javascript(笔记31) - BOM基本操作_javascript_27

注意:写入样式只能通过  div.style 这一个方法,没有其他方法了

查询计算样式

window.getComputedStyle(ele,null)  访问全部计算好的样式;

window.getComputedStyle(ele,null)[prop] 访问单个计算好的样式;

计算样式,只读;

返回的计算样式的值都是绝对值,没有相对单位;

IE8及以下不兼容;

要查看 div 的样式表:

Javascript(笔记31) - BOM基本操作_javascript_28

可以看到一堆计算好的样式,有些是设置过的(不论是div.style、style、还是行内还是引入的样式),都显示了;更多的是没有设置的样式,显示了默认值;如果使用相对单位(如:em),最终也会计算成像素PX,颜色也会计算成 RGB;

所以这个方法显示的是元素最终计算的真实显示的样式,且只读;

Javascript(笔记31) - BOM基本操作_BOM_29

第二个参数为什么是null?用来取伪元素的,也是只读。

window.getComputedStyle(div."after").width  // 获取 div::after 伪元素的 width

真要修改伪元素的样式,不如先把伪元素的样式写在 class 里,再修改 className ,好维护; 

div.className = "active"

封装兼容性方法

IE8及以下浏览器不兼容

div.currentStyle  

IE独有的,其他浏览器不能用;

function getStyle(elem,prop){
if(window.getComputedStyle){
return window.getComputedStyle(elem,null)[prop];
}else{
return elem.currentStyle[prop];
}
}


练习

让小方块移动

看下HTML:

<div style="width:100px;height:100px;background-color:red;position:absolute;"></div>

用JS来操作这个小方块:

var div = document.getElementsByTagName('div')[0];

var speed = 2; // 设置速度
var timer = setInterval(function () {
speed += speed / 5;
div.style.left = parseInt(getStyle(div, 'left')) + speed + "px";
if (parseInt(div.style.left) > 200) {
clearInterval(timer);
}
}, 100);

// 兼容性获取样式
function getStyle(elem, prop) {
if (window.getComputedStyle) {
return window.getComputedStyle(elem, null)[prop];
} else {
return elem.currentStyle[prop];
}
}





举报

相关推荐

0 条评论