js管理頁面元素位置大小

weixin_34129145發表於2018-02-03

網頁文件的大小和瀏覽器視窗的大小

首先,要明確兩個基本概念。
一張網頁的全部面積,就是它的大小。通常情況下,網頁的大小由網頁內容的多少和CSS樣式表決定。
瀏覽器視窗的大小,則是指在瀏覽器視窗中看到的那部分網頁面積,又叫做viewport(視口)。
很顯然,如果網頁的內容能夠在瀏覽器視窗中全部顯示(也就是不出現滾動條),那麼網頁的大小和瀏覽器視窗的大小是相等的。如果不能全部顯示,則滾動瀏覽器視窗,可以顯示出網頁的各個部分。

獲取視口的大小

網頁上的每個元素,都有clientHeight和clientWidth屬性。這兩個屬性指元素的內容部分再加上padding的所佔據的視覺面積,不包括border和滾動條佔用的空間。

468490-fdf4d90ff8fb854c.png
image.png

document元素的clientHeight和clientWidth屬性,就代表了視口的大小。

document.documentElement.clientWidth
 document.documentElement.clientHeight

使用的時候,有2個地方需要注意:

  • 這個函式必須在頁面載入完成後才能執行,否則document物件還沒生成,瀏覽器會報錯。
  • clientWidth和clientHeight都是隻讀屬性,不能對它們賦值。

元素.clientHeight 是元素內容的height+padding
比如:div.clientHeight

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #test{
            width: 100px;
            height: 150px;
            padding: 20px;
            border: 1px solid red;
        }
    </style>
</head>
<body>
<div id="test">
aaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaa
</div>

<script>
   console.log(document.documentElement.clientWidth);
   console.log(document.documentElement.clientHeight);
    var div = document.getElementById('test')

   console.log(div.clientWidth);
   console.log(div.clientHeight);
</script>
</body>
</html>

獲取網頁文件內容大小的方法(不包括溢位的內容)

document.documentElement.offsetWidth

獲取DOM文件的根節點html元素物件的寬度,即offsetWidth=width+padding+border,不包括margin。

document.documentElement.offsetHeight

獲取DOM文件的根節點html元素物件的高度,有可能小於視口高度(由文件內容高度決定,不包括溢位的內容),即offsetHeight=height+padding+border,不包括margin。

元素.offsetHeight是元素設定的height+padding+border(不包括溢位的內容)
比如:div.offsetHeight

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        #test{
            width: 100px;
            height: 150px;
            padding: 20px;
            border: 1px solid red;
        }
    </style>
</head>
<!--可以去掉style="height: 2000px"觀察一下-->
<body style="height: 2000px">
<div id="test">
aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
</div>

<script>
   console.log(document.documentElement.offsetWidth);
   console.log(document.documentElement.offsetHeight);
    var div = document.getElementById('test')

   console.log(div.offsetWidth);
   console.log(div.offsetHeight);
</script>
</body>
</html>

js實現小球觸壁反彈

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        #mainBox {
            width: 300px;
            height: 500px;
            background: lavender;
            border: 1px solid gold;
            margin: auto;
            position: relative;
        }

        .ball {
            width: 30px;
            height: 30px;
            background: cyan;
            border-radius: 50%;
            position: absolute;
            left: 0px;
            top: 0px;
        }

    </style>
</head>

<body>
<div id="mainBox">
    <div class="ball">

    </div>
</div>


</body>
<script type="text/javascript">
    //公共變數
    var ball_ = document.getElementsByClassName('ball')[0]
    var mainBox = document.getElementById("mainBox")


    //小球移動變數
    var x = 0;
    var y = 0;
    var speedX = 2;
    var speedY = 2;
    //定時器
    var timer = null;

    timer = setInterval('move()', 10)
    function move() {
        x += speedX;
        y += speedY;
        //判斷小球是否碰到邊界
        if(x <= 0 || x > mainBox.offsetWidth - ball_.offsetWidth) {
            speedX = -speedX
        }
        if(y <= 0 || mainBox.offsetHeight - ball_.offsetHeight <= y) {
            speedY = -speedY
        }
        //改變小球的left和top值
        ball_.style.left = x + 'px';
        ball_.style.top = y + 'px';

       }
    move();


</script>

</html>

獲取網頁文件內容大小的方法(包括溢位的內容)

網頁上的每個元素還有scrollHeight和scrollWidth屬性,指包含滾動條在內的該元素的視覺面積。
那麼,document物件的scrollHeight和scrollWidth屬性就是網頁的大小,意思就是滾動條滾過的所有長度和寬度。

        document.documentElement.scrollWidth
        document.documentElement.scrollHeight

元素.scrollHeight 可以獲得元素內容的實際高度,包括溢位的內容。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        #test{
            width: 100px;
            height: 150px;
            padding: 20px;
            border: 1px solid red;
        }
    </style>
</head>
<!--可以去掉style="height: 2000px"觀察一下-->
<body>
<div id="test">
aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaa
</div>

<script>
   console.log(document.documentElement.scrollWidth);
   console.log(document.documentElement.scrollHeight);
    var div = document.getElementById('test')

   console.log(div.scrollWidth);
   console.log(div.scrollHeight);
</script>
</body>
</html>

獲取網頁元素的絕對位置

網頁元素的絕對位置,指該元素的左上角相對於整張網頁左上角的座標。
這個絕對位置要通過計算才能得到。
首先,每個元素都有offsetTop和offsetLeft屬性,表示該元素的左上角與父容器(offsetParent物件)左上角的距離。所以,只需要將這兩個值進行累加,就可以得到該元素的絕對座標。


468490-58294e4665f2e800.png
image.png

下面兩個函式可以用來獲取絕對位置的橫座標和縱座標。

function getElementLeft(element){
    var actualLeft = element.offsetLeft;
    var current = element.offsetParent;

    while (current !== null){
      actualLeft += current.offsetLeft;
      current = current.offsetParent;
    }

    return actualLeft;
  }

  function getElementTop(element){
    var actualTop = element.offsetTop;
    var current = element.offsetParent;

    while (current !== null){
      actualTop += current.offsetTop;
      current = current.offsetParent;
    }

    return actualTop;
  }

body的offsetTop是0;body的offsetParent是null

offsetLeft與style.left的區別

offsetLeft 獲取的是相對於父物件的左邊距

left 獲取或設定相對於 具有定位屬性(position定義為relative)的父物件 的左邊距

如果父div的position定義為relative,子div的position定義為absolute,那麼子div的style.left的值是相對於父div的值,
這同offsetLeft是相同的,區別在於:

  1. style.left 返回的是字串,如28px,offsetLeft返回的是數值28,如果需要對取得的值進行計算,
    還用offsetLeft比較方便。
  2. style.left是讀寫的,offsetLeft是隻讀的,所以要改變div的位置,只能修改style.left。
  3. style.left的值需要事先定義,否則取到的值為空。而且必須要定義在html裡,我做過試驗,如果定義在
    css裡,style.left的值仍然 為空,這就是我剛開始碰到的問題,總是取不到style.left的值。

offsetLeft則仍然能夠取到,無需事先定義div的位置。

獲取網頁元素的相對位置

網頁元素的相對位置,指該元素左上角相對於瀏覽器視窗左上角的座標。
有了絕對位置以後,獲得相對位置就很容易了,只要將絕對座標減去頁面的滾動條滾動的距離就可以了。滾動條滾動的垂直距離,是document物件的scrollTop屬性;滾動條滾動的水平距離是document物件的scrollLeft屬性。


468490-367d7a388e4d4811.png
image.png

滾動距離

document.body.scrollTop/scrollLeft
scrollTop是可視區頂部到整個頁面頂部的距離(就是滾動條滾動距離);想要得到誰的滾動距離,scrollTop和scrollLeft的前面就寫哪個元素

document.documentElement.scrollTop/scrollLeft

相容性問題

chrome瀏覽器,認為滾動距離是在body上的

其他瀏覽器,認為滾動距離是documentElement上的

可以用如下方式解決相容性問題:

var scrollTop = document.documentElement.scrollTop || document.body.scrollTop

對上一節中的兩個函式進行相應的改寫,獲得元素的相對位置:

function getElementViewLeft(element){
    var actualLeft = element.offsetLeft;
    var current = element.offsetParent;

    while (current !== null){
      actualLeft += current.offsetLeft;
      current = current.offsetParent;
    }

   
    var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft

    return actualLeft-scrollLeft ;
  }

  function getElementViewTop(element){
    var actualTop = element.offsetTop;
    var current = element.offsetParent;

    while (current !== null){
      actualTop += current. offsetTop;
      current = current.offsetParent;
    }

  

    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop

    return actualTop-scrollTop;
  }

js實現返回頂部功能

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>test</title>
    <style>
        body {
            /*height: 5000px;*/
        }
        a {
            position: fixed;
            right: 100px;
            width: 50px;
            height: 50px;
            background: red;
            color: white;
            text-align: center;
            line-height: 50px;
            display: block;
        }
        .toTop {
            bottom: 160px;
        }
        .toBottom {
            bottom: 100px;
        }
    </style>
    <script>
        window.onload = function () {
            var a = document.getElementById('top');
            a.onclick = function () {
                var timeId = setInterval(function () {
                    var scroll_top = document.documentElement.scrollTop || document.body.scrollTop;
                    if(scroll_top == 0)
                    {
                        alert('計時器停止了')
                        clearInterval(timeId);
                    }
                    window.scrollBy(0,-100);

                },50);
            }

            var aBottom = document.getElementById('bottom');

            var viewportHeight = document.documentElement.clientHeight;
            var documentHeight = document.documentElement.scrollHeight;

            aBottom.onclick = function () {
                var timeId = setInterval(function () {
                    var scroll_top = document.documentElement.scrollTop || document.body.scrollTop;
                    if(scroll_top + viewportHeight == documentHeight)
                    {
                        alert('計時器停止了')
                        clearInterval(timeId);
                    }
                    window.scrollBy(0,100);

                },50);
            }
        }
    </script>
</head>

<body style="height: 5000px">
<a href="javascript:;" class="toTop" id ="top">上</a>
<a href="javascript:;" class="toBottom" id="bottom">下</a>
</body>
</html>


下拉載入模擬

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        window.onscroll=function() {
                console.log('正在滑動f');
                var scrollTop = document.documentElement.scrollTop;    //滾動條距離頂部的高度
                var scrollHeight = document.documentElement.scrollHeight;   //當前頁面的總高度
                var clientHeight = document.documentElement.clientHeight;    //當前可視的頁面高度
                 console.log("top:"+scrollTop+",doc:"+scrollHeight+",client:"+clientHeight);
                if (scrollTop + clientHeight >= scrollHeight) {   //距離頂部+當前高度 >=文件總高度 即代表滑動到底部
                    console.log('下拉');
                    var div = document.createElement('div');
                    div.style.height = 2000+'px';
                    document.getElementById('body').appendChild(div);
                }
            }

    </script>
</head>
<body id="body">
<div style="height: 2000px;" id = "div">

</div>
</body>
</html>

獲取元素相對位置的快速方法

除了上面的函式以外,還有一種快速方法,可以立刻獲得網頁元素的位置。
那就是使用getBoundingClientRect()方法。它返回一個物件,其中包含了left、right、top、bottom四個屬性,分別對應了該元素的左上角和右下角相對於瀏覽器視窗(viewport)左上角的距離。
所以,網頁元素的相對位置就是

var X= 元素.getBoundingClientRect().left;

 var Y =元素.getBoundingClientRect().top;

再加上滾動距離,就可以得到絕對位置

 var X=元素.getBoundingClientRect().left+document.documentElement.scrollLeft;

 var Y =元素.getBoundingClientRect().top+document.documentElement.scrollTop;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        div{
            height: 100px;
            width: 100px;
            background-color: red;
            position: absolute;
            left:200px;
            top: 1000px;
        }
        #btn{
            position: fixed;
            top:20px;
        }
    </style>
    <script>
        window.onload = function () {
            var btn = document.getElementById('btn');

            btn.onclick = function () {
                var scroll_top = document.documentElement.scrollTop || document.body.scrollTop;
                var div = document.getElementById('div')
                var obj = div.getBoundingClientRect();
                console.log("left" + obj.left);//200,div左邊距離視口左邊的距離
                console.log("top" + obj.top);//300,div頂邊距離視口頂邊的距離
                console.log("right" + obj.right);//300,div右邊距離視口左邊的距離
                console.log("bottom" + obj.bottom);//400,div底邊距離視口頂邊的距離
                console.log("scroll_top" + scroll_top);
                console.log("top絕對" + (obj.top+scroll_top));
            }

        }
    </script>
</head>
<body style="height: 2000px">
<div id="div">

</div>
<input type="button" id="btn" value="ok">
</body>
</html>


相關文章