• 深入理解元素视图的3个方法


    前面的话

      前面介绍了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 height
    IE8-:  top left right bottom

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

    <div id="test" style=" 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-width
    
    Element.getBoundingClientRect().height =  border-top-width + padding-top + height + padding-bottom + border-bottom-width

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

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

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

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

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

    bottom = top + height
    right = left + width

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

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

    bug

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

    <body style="margin:0">
    <div id="test" style=" 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=" 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) 72
    console.log(test.getClientRects()[0].height,test.getBoundingClientRect().height)
    </script>

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

    <body style="margin:0">
    <div style="100px;"><span id="el">
    Hello World
    Hello World
    Hello World
    </span></div>
    <script>
    console.log(el.getClientRects().length); // 3
    console.log(el.getClientRects()[0].left); // 0
    console.log(el.getClientRects()[0].right); // 88
    console.log(el.getClientRects()[0].bottom); // 17
    console.log(el.getClientRects()[0].height); // 16
    console.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=" 100px;height: 100px;">
        <span id="span1">123</span>
    </div>
    <script>
    console.log(document.elementFromPoint(2,2).id); //span1
    </script>
  • 相关阅读:
    linux添加自定义命令
    linux 将自己的服务添加到系统service服务
    制作linux下的.run安装包
    Wowza 相关
    深入理解 Vue Computed 计算属性
    养狗相关知识整理
    柯基犬体重对照图
    window下tomcat的内存溢出问题
    postMan测试https接口
    beego获取用户请求参数的方法
  • 原文地址:https://www.cnblogs.com/xiaohuochai/p/5832712.html
Copyright © 2020-2023  润新知