js管理頁面元素位置大小

網(wǎng)頁文檔的大小和瀏覽器窗口的大小

首先,要明確兩個(gè)基本概念摄闸。
一張網(wǎng)頁的全部面積善镰,就是它的大小。通常情況下年枕,網(wǎng)頁的大小由網(wǎng)頁內(nèi)容的多少和CSS樣式表決定炫欺。
瀏覽器窗口的大小,則是指在瀏覽器窗口中看到的那部分網(wǎng)頁面積熏兄,又叫做viewport(視口)品洛。
很顯然树姨,如果網(wǎng)頁的內(nèi)容能夠在瀏覽器窗口中全部顯示(也就是不出現(xiàn)滾動(dòng)條),那么網(wǎng)頁的大小和瀏覽器窗口的大小是相等的桥状。如果不能全部顯示帽揪,則滾動(dòng)瀏覽器窗口,可以顯示出網(wǎng)頁的各個(gè)部分辅斟。

獲取視口的大小

網(wǎng)頁上的每個(gè)元素转晰,都有clientHeight和clientWidth屬性。這兩個(gè)屬性指元素的內(nèi)容部分再加上padding的所占據(jù)的視覺面積士飒,不包括border和滾動(dòng)條占用的空間查邢。


image

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

document.documentElement.clientWidth
 document.documentElement.clientHeight

使用的時(shí)候扰藕,有2個(gè)地方需要注意:

  • 這個(gè)函數(shù)必須在頁面加載完成后才能運(yùn)行,否則document對(duì)象還沒生成芳撒,瀏覽器會(huì)報(bào)錯(cuò)邓深。
  • clientWidth和clientHeight都是只讀屬性,不能對(duì)它們賦值番官。

元素.clientHeight 是元素內(nèi)容的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>

獲取網(wǎng)頁文檔內(nèi)容大小的方法(不包括溢出的內(nèi)容)

document.documentElement.offsetWidth

獲取DOM文檔的根節(jié)點(diǎn)html元素對(duì)象的寬度,即offsetWidth=width+padding+border钢属,不包括margin徘熔。

document.documentElement.offsetHeight

獲取DOM文檔的根節(jié)點(diǎn)html元素對(duì)象的高度,有可能小于視口高度(由文檔內(nèi)容高度決定淆党,不包括溢出的內(nèi)容)酷师,即offsetHeight=height+padding+border,不包括margin染乌。

元素.offsetHeight是元素設(shè)定的height+padding+border(不包括溢出的內(nèi)容)
比如: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實(shí)現(xiàn)小球觸壁反彈

<!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")

    //小球移動(dòng)變量
    var x = 0;
    var y = 0;
    var speedX = 2;
    var speedY = 2;
    //定時(shí)器
    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>

獲取網(wǎng)頁文檔內(nèi)容大小的方法(包括溢出的內(nèi)容)

網(wǎng)頁上的每個(gè)元素還有scrollHeight和scrollWidth屬性山孔,指包含滾動(dòng)條在內(nèi)的該元素的視覺面積。
那么荷憋,document對(duì)象的scrollHeight和scrollWidth屬性就是網(wǎng)頁的大小台颠,意思就是滾動(dòng)條滾過的所有長(zhǎng)度和寬度。

        document.documentElement.scrollWidth
        document.documentElement.scrollHeight

元素.scrollHeight 可以獲得元素內(nèi)容的實(shí)際高度勒庄,包括溢出的內(nèi)容串前。

<!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>

獲取網(wǎng)頁元素的絕對(duì)位置

網(wǎng)頁元素的絕對(duì)位置,指該元素的左上角相對(duì)于整張網(wǎng)頁左上角的坐標(biāo)实蔽。
這個(gè)絕對(duì)位置要通過計(jì)算才能得到荡碾。
首先,每個(gè)元素都有offsetTop和offsetLeft屬性局装,表示該元素的左上角與父容器(offsetParent對(duì)象)左上角的距離坛吁。所以劳殖,只需要將這兩個(gè)值進(jìn)行累加,就可以得到該元素的絕對(duì)坐標(biāo)拨脉。

image

下面兩個(gè)函數(shù)可以用來獲取絕對(duì)位置的橫坐標(biāo)和縱坐標(biāo)哆姻。

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的區(qū)別

offsetLeft 獲取的是相對(duì)于父對(duì)象的左邊距

left 獲取或設(shè)置相對(duì)于 具有定位屬性(position定義為relative)的父對(duì)象 的左邊距

如果父div的position定義為relative,子div的position定義為absolute女坑,那么子div的style.left的值是相對(duì)于父div的值填具,
這同offsetLeft是相同的,區(qū)別在于:

  1. style.left 返回的是字符串匆骗,如28px劳景,offsetLeft返回的是數(shù)值28,如果需要對(duì)取得的值進(jìn)行計(jì)算碉就,
    還用offsetLeft比較方便盟广。
  2. style.left是讀寫的,offsetLeft是只讀的瓮钥,所以要改變div的位置筋量,只能修改style.left。
  3. style.left的值需要事先定義碉熄,否則取到的值為空桨武。而且必須要定義在html里,我做過試驗(yàn)锈津,如果定義在
    css里呀酸,style.left的值仍然 為空,這就是我剛開始碰到的問題琼梆,總是取不到style.left的值性誉。

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

獲取網(wǎng)頁元素的相對(duì)位置

網(wǎng)頁元素的相對(duì)位置错览,指該元素左上角相對(duì)于瀏覽器窗口左上角的坐標(biāo)。
有了絕對(duì)位置以后煌往,獲得相對(duì)位置就很容易了倾哺,只要將絕對(duì)坐標(biāo)減去頁面的滾動(dòng)條滾動(dòng)的距離就可以了。滾動(dòng)條滾動(dòng)的垂直距離刽脖,是document對(duì)象的scrollTop屬性悼粮;滾動(dòng)條滾動(dòng)的水平距離是document對(duì)象的scrollLeft屬性。

image

滾動(dòng)距離

document.body.scrollTop/scrollLeft
scrollTop是可視區(qū)頂部到整個(gè)頁面頂部的距離(就是滾動(dòng)條滾動(dòng)距離)曾棕;想要得到誰的滾動(dòng)距離扣猫,scrollTop和scrollLeft的前面就寫哪個(gè)元素

document.documentElement.scrollTop/scrollLeft

兼容性問題

chrome瀏覽器,認(rèn)為滾動(dòng)距離是在body上的

其他瀏覽器翘地,認(rèn)為滾動(dòng)距離是documentElement上的

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

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

對(duì)上一節(jié)中的兩個(gè)函數(shù)進(jìn)行相應(yīng)的改寫,獲得元素的相對(duì)位置:

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實(shí)現(xiàn)返回頂部功能

<!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 oA = document.getElementsByTagName('a');

            oA[0].onclick = function() {
                toScroll("top")
            }
            oA[1].onclick = function() {
                toScroll("bottom")
            }
        }
        function toScroll(target) {
            clearInterval(this.timer)
            var scrollHeight = document.body.offsetHeight - document.documentElement.clientHeight;
            this.timer = setInterval(function() {
                var scrolltop = document.documentElement.scrollTop || document.body.scrollTop;
                switch (target) {
                    case 'top':
                        console.log(scrolltop);
                        //把內(nèi)容滾動(dòng)指定的像素?cái)?shù)(第一個(gè)參數(shù)向右滾動(dòng)的像素?cái)?shù)申尤,第二個(gè)參數(shù)向下滾動(dòng)的像素?cái)?shù))
                        window.scrollBy(0, -100);
                        if (Math.ceil(scrolltop) <= 0) {
                            clearInterval(this.timer)
                        };
                        break;
                    case 'bottom':
                        console.log(scrolltop);
                        window.scrollBy(0, 100);
                        if (Math.ceil(scrolltop) >= scrollHeight) {
                            clearInterval(this.timer)
                        };
                        break;
                }
            }, 30)
        }
    </script>
</head>

<body>
<a href="javascript:;" class="toTop">上</a>
<a href="javascript:;" class="toBottom">下</a>
</body>

</html>

獲取元素相對(duì)位置的快速方法

除了上面的函數(shù)以外癌幕,還有一種快速方法,可以立刻獲得網(wǎng)頁元素的位置昧穿。
那就是使用getBoundingClientRect()方法勺远。它返回一個(gè)對(duì)象,其中包含了left时鸵、right胶逢、top、bottom四個(gè)屬性饰潜,分別對(duì)應(yīng)了該元素的左上角和右下角相對(duì)于瀏覽器窗口(viewport)左上角的距離初坠。
所以,網(wǎng)頁元素的相對(duì)位置就是

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

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

再加上滾動(dòng)距離彭雾,就可以得到絕對(duì)位置

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

 var Y =元素.getBoundingClientRect().top+document.documentElement.scrollTop;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末碟刺,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子薯酝,更是在濱河造成了極大的恐慌半沽,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吴菠,死亡現(xiàn)場(chǎng)離奇詭異者填,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)做葵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門占哟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蜂挪,你說我怎么就攤上這事重挑∩せ” “怎么了棠涮?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)刺覆。 經(jīng)常有香客問我严肪,道長(zhǎng),這世上最難降的妖魔是什么谦屑? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任驳糯,我火速辦了婚禮,結(jié)果婚禮上氢橙,老公的妹妹穿的比我還像新娘酝枢。我一直安慰自己,他們只是感情好悍手,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布帘睦。 她就那樣靜靜地躺著袍患,像睡著了一般。 火紅的嫁衣襯著肌膚如雪竣付。 梳的紋絲不亂的頭發(fā)上诡延,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音古胆,去河邊找鬼肆良。 笑死,一個(gè)胖子當(dāng)著我的面吹牛逸绎,可吹牛的內(nèi)容都是我干的惹恃。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼桶良,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼座舍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起陨帆,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤曲秉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后疲牵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體承二,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年纲爸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了亥鸠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡识啦,死狀恐怖负蚊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情颓哮,我是刑警寧澤家妆,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站冕茅,受9級(jí)特大地震影響伤极,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜姨伤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一哨坪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧乍楚,春花似錦当编、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拧篮。三九已至,卻和暖如春牵舱,著一層夾襖步出監(jiān)牢的瞬間串绩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來泰國打工芜壁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留礁凡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓慧妄,卻偏偏與公主長(zhǎng)得像顷牌,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子塞淹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容