你的位置:首页 > Java教程

[Java教程]深入理解元素视图的3个方法


×
目录
[1]BoundingClient [2]ClientRects [3]elementFromPoint

前面的话

  前面介绍了offset偏移、client可视区和scroll滚动,这三部分主要从属性的角度来对元素尺寸信息进行获取和修改。本文主要介绍元素视图的三个方法,包括getBoundingClientRect()、getClientRects()和elementFromPoint()

 

getBoundingClientRect()

  判断一个元素的尺寸和位置是简单的方法就是使用getBoundingClientRect()

  Element.getBoundingClientRect()方法返回一个对象,该对象提供当前元素节点的大小、它相对于视口(viewport)的位置等信息。但是,各个浏览器返回的对象包含的属性不相同

firefox: top left right bottom width height x y(其中,x=left,y=top)chrome/safari/IE9+:top left right bottom width heightIE8-: top left right bottom

  问题来了,该方法返回的width和height是可视宽高client,还是滚动宽高scroll,或者是偏移宽高offset,或者是设置宽高呢

<div id="test" style="width: 100px;height: 100px;padding: 10px;line-height: 200px;border:1px solid black;overflow:scroll">内容</div>  <script>//chrome/safari: 220(10+200+10)//firefox/IE: 210(10+200)console.log(test.scrollHeight)//103(100+10+10-17)console.log(test.clientHeight)//122(100+10+10+1+1)console.log(test.offsetHeight)//122(100+10+10+1+1)console.log(test.getBoundingClientRect().height)</script>

  由代码结果看出,该方法返回的宽高是偏移宽高offset

Element.getBoundingClientRect().width = border-left-width + padding-left + width + padding-right + border-right-widthElement.getBoundingClientRect().height = border-top-width + padding-top + height + padding-bottom + border-bottom-width

  下面来分析top、left、right、bottom这四个值

  top:   元素顶部相对于视口的纵坐标

  left:  元素左边界相对视口的横坐标

  right: 元素右边界相对视口的横坐标

  bottom:元素底部相对于视口的纵坐标

bottom = top + heightright = left + width

  [注意]该方法的所有属性值都没有单位,且给定的是元素在页面中相对于视口的位置

  问题又来了,相对于视口和相对于页面有什么区别。理论上,与absolute和fixed的区别类似,但表现上与它们正相反。发生滚动时,fixed元素保持不动是为了保持与视口的原始距离;而发生滚动时,getBoundingClientRect()方法的top、left、right、bottom这四个值相应的发生改变,是因为元素位置移动了,与视口距离自然也改变了

bug

  IE7-浏览器把视口的左上角坐标设置为(2,2),其他浏览器则将(0,0)作为起点坐标

<body style="margin:0"><div id="test" style="width: 100px;height: 50px;padding: 10px;line-height: 200px;overflow:scroll;border:1px solid black">内容</div>  <script>//chrome/firefox/safari/IE8+ 0 72(50+10+10+1+1)//IE7- 2 74(72+2)console.log(test.getBoundingClientRect().top,test.getBoundingClientRect().bottom)//chrome/firefox/safari/IE8+ 0 122(100+10+10+1+1)//IE71 2 124(122+2)console.log(test.getBoundingClientRect().left,test.getBoundingClientRect().right)</script></body>

兼容

  可以利用IE7-浏览器中特性节点的specified属性实现浏览器识别

function getBoundingClientRect(obj){  var temp = obj.getBoundingClientRect();  //IE7-浏览器  if(Boolean(obj.attributes[0]) && !obj.attributes[0].specified){    return{      left: temp.left -2,      top: temp.top -2,      right: temp.right -2,      bottom: temp.bottom -2    }  }else{    return temp;  }  }

 

getClientRects()

  getClientRects()方法与getBoundingClientRect()不同,该方法是一个返回元素的数个矩形区域的类数组对象。每个类数组对象的参数与getBoundingClientRect()方法相同,每个矩形都有bottom、height、left、right、top和width六个属性,表示它们相对于视口的四个坐标,以及本身的高度和宽度

  如果应用于块级元素,则getClientRects()[0]和getBoundingClientRect()的属性返回相同的值,且IE7-浏览器在getClientRects()方法中,同样存在 视口左上角坐标被设置为(2,2)的bug

<body style="margin:0"><div id="test" style="width: 100px;height: 50px;padding: 10px;line-height: 200px;overflow:scroll;border:1px solid black">内容</div>  <script>//其他浏览器返回0 0, IE7-浏览器返回 2 2 console.log(test.getClientRects()[0].top,test.getBoundingClientRect().top)//其他浏览器返回0 0, IE7-浏览器返回 2 2 console.log(test.getClientRects()[0].left,test.getBoundingClientRect().left)//72(50+10+10+1+1) 72console.log(test.getClientRects()[0].height,test.getBoundingClientRect().height)</script>

  实际上,该方法主要用于内联元素,内联元素有多少行,该方法返回的对象有多少个成员。这个方法主要用于判断行内元素是否换行,以及行内元素的每一行的位置偏移

<body style="margin:0"><div style="width:100px;"><span id="el">Hello WorldHello WorldHello World</span></div><script>console.log(el.getClientRects().length); // 3console.log(el.getClientRects()[0].left); // 0console.log(el.getClientRects()[0].right); // 88console.log(el.getClientRects()[0].bottom); // 17console.log(el.getClientRects()[0].height); // 16console.log(el.getClientRects()[0].width); // 88</script></body>

 

elementFromPoint()

  getBoundingClientRect(x,y)方法使我们能在视口中判定元素的位置。但有时我们想反过来,判定在视口中的指定位置上有什么元素。这可以用Document对象的elementFromPoint()方法来判定。传递X和Y坐标(相对于视口),该方法选择在指定坐标的最上层和最里层的Element对象。如果指定的点在视口以外,elementFromPoint()返回null

  [注意]最上层是指z-index最大的元素;最里层是指最里层的子元素

  这个方法可以用来检测元素是否发生重叠或是碰撞

<body style="margin:0"><div id="test" style="width: 100px;height: 100px;">  <span id="span1">123</span></div><script>console.log(document.elementFromPoint(2,2).id); //span1</script>