文檔坐標(biāo)和視口坐標(biāo):
元素的位置是以像素來度量的,向右代表x坐標(biāo)的增加,向下代表y坐標(biāo)的增加;但是,有兩個(gè)不同的點(diǎn)作為坐標(biāo)系的原點(diǎn):元素的x和y坐標(biāo)可以相對于文檔的左上角或者相對于視口的左上角,也就是對于一個(gè)元素來說,會(huì)有兩種坐標(biāo):文檔坐標(biāo)和視口坐標(biāo);視口坐標(biāo)也被稱為窗口坐標(biāo);
在頂級窗口或標(biāo)簽頁中,視口只是實(shí)際顯示文檔內(nèi)容的瀏覽器的一部分 , 它不包括瀏覽器其他組件,如菜單、工具條等;
對于在框架中顯示的文檔,視口是定義了框架頁的<iframe>元素;
元素大?。?
以下的屬性和方法不屬于DOM2級樣式規(guī)范,但卻與HTML元素的樣式息息相關(guān);IE率先引用了一些屬性,目前,所有主流的瀏覽器都支持以下屬性;
1. 偏移量(offset dimension):
包括元素在屏幕上占用的所有可見的空間;元素的可見大小包括寬高 , 所有內(nèi)邊距,滾動(dòng)條和邊框的大小(不包括外邊距);
通過以下4個(gè)屬性可以取得元素的偏移量:
- offsetWidth:元素在水平方向占用的空間大小,以像素計(jì),包括元素的寬度 , (可見的)垂直滾動(dòng)條的寬度,左右邊框?qū)挾龋?/li>
- offsetHeight:元素在垂直方向占用的空間大??,翼嶑素?,包括元素的高度 , (可見的)水平滾動(dòng)條的高度,上下邊框高度;
- offsetLeft:元素的左外邊框到包含元素的左內(nèi)邊框之間的像素距離,即元素的x坐標(biāo);
- offsetTop:元素的上外邊框到包含元素的上內(nèi)邊框之間的像素距離,即元素的y坐標(biāo);

文章插圖
偏移量(offset dimension)
var mydiv = document.getElementById("mydiv");console.log(mydiv.offsetWidth);console.log(mydiv.offsetHeight);console.log(mydiv.offsetLeft);console.log(mydiv.offsetTop);offsetLeft和offsetTop返回值與包含元素有關(guān),對于有些元素,這些值是文檔坐標(biāo) , 但對于已定位元素的后代元素和一些其他元素(如表格單元格),這些屬性返回的坐標(biāo)是相對于祖先元素而不是文檔;offsetParent屬性:包含元素的引用 , 也就是相對的父元素;offsetParent不一定與parentNode的值相等;如:<td>元素的offsetParent是作為其祖先元素的<table>元素,因?yàn)?lt;table>是在DOM層次中距<td>最近的一個(gè)具有大小的元素;
如果其offsetParent屬性為null,以上的屬性都是文檔坐標(biāo);
console.log(mydiv.offsetParent);如果要想知道某個(gè)元素在頁面上的偏移量,將這個(gè)元素的offsetLeft和offsetTop與其offsetParent的相同屬性相加,如此循環(huán)直至根元素 , 就可以得到一個(gè)基本準(zhǔn)確的值;<style>*{margin: 0; padding: 0;}ul,li{list-style: none;}#container{width: 500px; height:100px; position: absolute;left:50px;top:100px;border:10px solid;background-color: blue;}#content{width: 400px; height:50px; position: relative; padding-left: 50px;background-color: red; }#myul{width: 300px; position: relative; background-color: purple;}#myli{width: 200px; margin-left:20px; background-color: pink;}</style><body><div id="container"><div id="content"><ul id="myul"><li id="myli">零點(diǎn)程序員</li></ul></div></div><script>var myli = document.getElementById("myli");console.log(myli.offsetWidth);console.log(myli.offsetLeft);console.log(myli.offsetParent);var myul = document.getElementById("myul");console.log(myul.offsetWidth);console.log(myul.offsetLeft);console.log(myul.offsetParent);var content = document.getElementById("content");console.log(content.offsetWidth);console.log(content.offsetLeft);console.log(content.offsetParent);var container = document.getElementById("container");console.log(container.offsetWidth);console.log(container.offsetLeft);console.log(container.offsetParent);// 定義一個(gè)函數(shù)function getElementPosition(element){var x = 0, y = 0;while(element != null){x += element.offsetLeft;y += element.offsetTop;element = element.offsetParent;}return {x:x, y:y};}var content = document.getElementById("content");console.log(getElementPosition(content).x);console.log(getElementPosition(content).y);var myli = document.getElementById("myli");console.log(getElementPosition(myli).x);console.log(getElementPosition(myli).y);</script>但實(shí)際上這個(gè)函數(shù)返回的值是不正確的,因?yàn)闆]有包括邊框的寬度;既然offsetWidth和offsetHeight是包括border的寬度的,所以有些地方也把它稱為物理寬度 , 它的值就是該元素實(shí)際的尺寸 , 因此 , 這并不一定等于元素的width和height,只有元素的CSS設(shè)置了box-sizing:border-box時(shí)才相等;
對于一個(gè)元素來說 , 它的實(shí)際的寬高也并不一定等于它的內(nèi)容的寬和高 , 也就是在擁有滾動(dòng)條的情況下,如:
<style>#mydiv{width: 300px; height: 100px;border: 1px solid; overflow: scroll;}</style><div id="mydiv">Lorem more...</div><script>var mydiv = document.getElementById("mydiv");console.log(mydiv.offsetWidth);// 302console.log(mydiv.offsetHeight); // 102console.log(mydiv.scrollWidth);// 283console.log(mydiv.scrollHeight);// 483</script>另外 , 這兩個(gè)屬性值也不包含元素的:before或:after等偽類的寬和高;<style>#mydiv{width: 300px; height: 100px;border: 1px solid;}#mydiv::after{content: "web前端開發(fā)"; display: block; margin-top:100px;}</style><div id="mydiv"></div><script>var mydiv = document.getElementById("mydiv");console.log(mydiv.offsetWidth);// 302console.log(mydiv.offsetHeight);// 102</script>如果該元素的display:none , 各屬性返回0,offsetParent返回null;【關(guān)于JS獲取子頁面的鼠標(biāo)坐標(biāo) js獲取元素位置坐標(biāo)的方法】如果該元素的position為static或fixed,其offsetParent為null,此時(shí)返回的各個(gè)屬性值就是文檔坐標(biāo);
對于行盒元素(如 span),offsetTop和offsetLeft描述的是第一個(gè)邊界框的位置,offsetWidth和 offsetHeight描述的是邊界框的尺寸;因此 , 使用offsetLeft、offsetTop、offsetWidth、offsetHeight來對應(yīng)left、top、width和height 的一個(gè)盒子將不會(huì)是文本容器 span 的盒子邊界;如:
<div style="width: 300px; border:1px solid blue;"><span style="background-color: purple;">span element</span><span id="long">Lorem ... text more...</span></div><div id="box" style="position: absolute; border: 1px solid red; z-index: 10"></div><script>var box = document.getElementById("box");var long = document.getElementById("long");box.style.left = long.offsetLeft + "px";box.style.top = long.offsetTop + "px";box.style.width = long.offsetWidth + "px";box.style.height = long.offsetHeight + "px";</script>所有這些偏移量屬性都是只讀的,且每次訪問它們都需要重新計(jì)算;因此 , 應(yīng)該盡量避免重復(fù)訪問這些屬性;如果要使用,可以將它們保存在局部變量中,以提高性能;myul.offsetLeft = 20;console.log(myul.offsetLeft);// 50 靜默失敗2.客戶區(qū)大小(client dimension):指的是元素內(nèi)容及其內(nèi)邊距所占據(jù)的空間大小,相關(guān)屬性為:clientTop、clientLeft、clientWidth和clientHeight;

文章插圖
客戶區(qū)大小(client dimension)
客戶區(qū)大小就是元素內(nèi)部的空間大小,其與offsetWidth和offsetHeight類似 , 只不過不包含邊框大??;也苍掽括过f跽加玫目占洌?
clientWidth = CSS width + CSS padding – 水平滾動(dòng)條寬度 – CSS border(如果width不包括border的話);
clientHeight = CSS height + CSS padding – 水平滾動(dòng)條高度 – CSS border(如果height不包括border的話);
var mydiv = document.getElementById("mydiv");console.log(mydiv.clientWidth);console.log(mydiv.clientHeight);注意,它不是元素內(nèi)容實(shí)際的尺寸,而是元素內(nèi)部可見區(qū)域的大??;并且是苍掽括过f醯?nbsp;, 如:<style>#mydiv{width: 300px; height: 100px;padding: ;border: 1px solid; overflow: scroll;}</style><div id="mydiv">Lorem more...</div><script>var mydiv = document.getElementById("mydiv");console.log(mydiv.offsetWidth);// 302console.log(mydiv.offsetHeight); // 102console.log(mydiv.clientWidth);// 300console.log(mydiv.clientHeight); // 100console.log(mydiv.scrollWidth);// 300console.log(mydiv.scrollHeight); // 147注意:對于行盒,如<i>、<code>或<span>等,包括塊盒被設(shè)置了display:block后,clientWidth和clientHeight總是返回0;當(dāng)元素的display:none時(shí) , 返回的也是0;
var span = document.getElementsByTagName("span")[0];console.log(span.clientWidth);// 0console.log(span.clientHeight);// 0最典型的應(yīng)用就是之前講到的獲得瀏覽器視口大小 , 如:function getViewPort(){if(document.compatMode == "BackCompat"){return{width:document.body.clientWidth,height:document.body.clientHeight};}else{return {width:document.documentElement.clientWidth,height:document.documentElement.clientHeight};}}有一個(gè)特例:在文檔的根元素上使用這些屬性時(shí),它們的返回值和窗口的innerWidth和innerHeight屬性值相等;但如果有滾動(dòng)條的話,innerWidth和innerHeight包括滾動(dòng)條占用空間的值;console.log(document.documentElement.clientWidth, document.documentElement.clientHeight);console.log(window.innerWidth, window.innerHeight);獲得瀏覽器視口大?。?function getViewportSize(w){// 使用指定的窗口,如果不帶參數(shù)則使用當(dāng)前窗口w = w || window;if(w.innerWidth != null) return {w: w.innerWidth, h: w.innerHeight};var d = w.document;if(document.compatMode == "CSS1Compat")return {w: d.documentElement.clientWidth, h: d.documentElement.clientHeight};// 怪異模式return {w: d.body.clientWidth, h: d.body.clientHeight};}console.log(getViewportSize().h);與偏移量相似,這兩個(gè)屬性該也為只讀,并且每次訪問都要重新計(jì)算;clientTop屬性和clientLeft屬性:可以返回元素的上邊框和左邊框的大小,其值為一個(gè)整數(shù) , 沒有單位,并且是只讀的;
var mydiv = document.getElementById("mydiv");console.log(mydiv.clientTop);// 1console.log(mydiv.clientLeft);// 1其和getComputedStyle ()方法的borderTopWidth屬性存在一定的區(qū)別;var mydiv = document.getElementById("mydiv");console.log(mydiv.clientTop);// 12console.log(getComputedStyle(mydiv,null).borderTopWidth);// 11.5px可見,clientTop和clientLeft返回的是整數(shù)并且沒有單位,而borderTopWidth返回的是mydiv的上邊框的厚度,是精確的;兩者之間的關(guān)系是:mydiv.clientTop = Math.round(parseFloat(getComputedStyle(mydiv,null).borderTopWidth));但firefox是向下取整;如果元素有滾動(dòng)條,并且將這些滾動(dòng)條放在左側(cè)或頂部,clientLeft和clientTop也就包含了滾動(dòng)條的寬度;
對于行盒元素來說,clientLeft和clientTop值總是為0;當(dāng)元素的display:none時(shí),返回的也是0;
3.滾動(dòng)大小(scroll dimension):
指的是包含滾動(dòng)內(nèi)容的元素大?。?
有些元素(如<html>),即使沒有執(zhí)行任何代碼也能自動(dòng)地添加滾動(dòng)條;但另外一些元素,則需要通過css的overflow屬性進(jìn)行設(shè)置才能滾動(dòng);
滾動(dòng)相關(guān)的屬性:
- scrollHeight:在沒有滾動(dòng)條的情況下,元素內(nèi)容的總高度;
- scrollWidth:在沒有滾動(dòng)條的情況下 , 元素內(nèi)容的總寬度;(這兩個(gè)屬性前面用過了)
- scrollLeft:被隱藏在內(nèi)容區(qū)域左側(cè)的像素?cái)?shù);通過設(shè)置該屬性可以改變元素的滾動(dòng)位置;
- scrollTop:被隱藏在內(nèi)容區(qū)域上方的像素?cái)?shù);通過設(shè)置這個(gè)屬性可以改變元素的滾動(dòng)位置;

文章插圖
滾動(dòng)大小(scroll dimension)
scrollWidth和scrollHeight主要用于確定元素內(nèi)容的實(shí)際大??,它们是謿g戀?,苍掽括眹诚柾过f酰?
也就是說,返回的是元素的內(nèi)容區(qū)域加上它的內(nèi)邊距再加上任何溢出內(nèi)容的尺寸;
<style>#mydiv{width: 300px;height:100px; border: 1px solid; overflow: scroll;}</style><div id="mydiv">Lorem more...</div><script>var mydiv = document.getElementById("mydiv");// 283 = 300 -17(滾動(dòng)條的寬), 168 = 內(nèi)容實(shí)際的高 console.log(mydiv.scrollWidth, mydiv.scrollHeight);</script>當(dāng)內(nèi)容正好和內(nèi)容區(qū)域匹配而沒有溢出時(shí),這些屬性與clientWidth與clientHeight是相等的;但當(dāng)溢出時(shí),它們就包含溢出的內(nèi)容,返回值比clientWidth和clientHeight要大;// 改變文字?jǐn)?shù)量,觀察兩者的區(qū)別console.log(mydiv.scrollWidth, mydiv.scrollHeight);console.log(mydiv.clientWidth, mydiv.clientHeight);通常認(rèn)為<html>(混雜模式下為<body>)元素是在瀏覽器視口滾動(dòng)的元素,因此帶有垂直滾動(dòng)條的頁面總高度就是document.documentElement.scrollHeight;
對于不包含滾動(dòng)條的頁面,scrollWidth、scrollHeight和clientWidth、clientHeight之間的關(guān)系基本是相等的;
console.log(document.documentElement.scrollWidth, document.documentElement.scrollHeight);console.log(document.documentElement.clientWidth, document.documentElement.clientHeight);scrollWidth和scrollHeight等于文檔內(nèi)容區(qū)域的大??,而clientWidth和clientHeight等于視口大?。壞桶姹鏡匿榔饔鋅贍芙峁⒉灰恢?jǐn)n?在確定文檔的總高度時(shí),必須取得scrollWidth/clientWidth和scrollheight/clientHeight中的最大值,才能保證在跨瀏覽器的環(huán)境下得到精確的結(jié)果;
var docWidth = Math.max(document.documentElement.scrollWidth, document.documentElement.clientWidth);var docHeight = Math.max(document.documentElement.scrollHeight, document.documentElement.clientHeight);注:對于混雜混式下,需要使用document.bodyscrollLeft和scrollTop屬性:
通過這兩個(gè)屬性可以取得元素當(dāng)前滾動(dòng)的狀態(tài),也就是滾動(dòng)位置;它們是可寫的,即能設(shè)置元素的滾動(dòng)位置;
scrollLeft 屬性可以獲取或設(shè)置一個(gè)元素的內(nèi)容水平滾動(dòng)的像素?cái)?shù);scrollTop 屬性可以獲取或設(shè)置一個(gè)元素的內(nèi)容垂直滾動(dòng)的像素?cái)?shù);
在尚未滾動(dòng)時(shí),兩值均為0;如果垂直滾動(dòng),該值大于0,且表示元素上方不可見內(nèi)容的像素高度,如果水平滾動(dòng),該值大于0,且表示元素左方不可見內(nèi)容的像素寬;
console.log(document.documentElement.scrollLeft);console.log(document.documentElement.scrollTop);示例:滾動(dòng)一個(gè)元素;<style>#mydiv{width: 300px; height:100px; border: 2px solid; overflow: scroll hidden; white-space: nowrap;}</style><div id="mydiv">Lorem, more...</div><button id="btn">滾</button><script>var mydiv = document.getElementById("mydiv");var btn = document.getElementById("btn");btn.onclick = function(e){mydiv.scrollLeft += 20;}</script>將元素的這兩個(gè)屬性設(shè)置為0,就可以重置元素的滾動(dòng)位置;function scrollToTop(element){if(element.scrollTop != 0){element.scrollTop = 0;}}// 應(yīng)用var btn = document.getElementById("btn");btn.onclick = function(){scrollToTop(document.documentElement);}判定元素是否滾動(dòng)到底:如果元素滾動(dòng)到底,下面等式返回true,否則返回false,如:element.scrollHeight – element.scrollTop === element.clientHeight;var mydiv = document.getElementById("mydiv");var timer = setInterval(scrollDiv, 100);function scrollDiv(){if(mydiv.scrollHeight - mydiv.scrollTop === mydiv.clientHeight)clearInterval(timer);elsemydiv.scrollTop += 5;console.log("scroll");}檢查容器能否滾動(dòng):// 加個(gè)判斷,條件也可以是:// window.getComputedStyle(mydiv).overflow === 'hidden'var timer;if(window.getComputedStyle(mydiv).overflowY === 'scroll'){timer = setInterval(scrollDiv, 100);}scrollLeft和scrollTop可以被設(shè)置為任何整數(shù)值,但有以下特點(diǎn):- 如果一個(gè)元素不能被滾動(dòng)(例如 , 它沒有溢出),scrollTop將被設(shè)置為0;
- 設(shè)置的值小于0,這兩個(gè)屬性值被設(shè)為0;
- 如果設(shè)置了超出這個(gè)容器可滾動(dòng)的值,,這兩個(gè)屬性會(huì)被設(shè)為最大值;
var mydiv = document.getElementById("mydiv");mydiv.scrollTop = 500; // 或設(shè)為負(fù)數(shù)console.log(mydiv.scrollTop); // 0這兩個(gè)屬性值有可能是小數(shù)(比如縮放了頁面的顯示大?。?,所以灾R≈凳弊詈萌≌? ,例如:Math.ceil()或Math.floor;function getElementPos(element){var y = 0, x = 0;var current = element;for(var e = element; e != null; e = e.offsetParent){// 但是自己的邊框不能加進(jìn)去if(current == e){x += e.offsetLeft;y += e.offsetTop;}else{x += e.offsetLeft + e.clientLeft;y += e.offsetTop + e.clientTop;}}// 再次循環(huán)所有的祖先元素,減去滾動(dòng)的偏移量,并轉(zhuǎn)換為視口坐標(biāo)for(var e=element.parentNode; e != null && e.nodeType == 1; e = e.parentNode){y -= e.scrollTop;x -= e.scrollLeft;}return {x:x, y:y};}var mydiv = document.getElementById("mydiv");console.log(getElementPos(mydiv).x);console.log(getElementPos(mydiv).y);console.log(mydiv.offsetParent);console.log(mydiv.getBoundingClientRect());示例:返回到頂部:var gotop = document.getElementById("gotop");var timer;gotop.onclick = function(){timer = setInterval(goTop, 1);}function goTop(){if(document.documentElement.scrollTop == 0)clearInterval(timer);else{// document.documentElement.scrollTop-= 10;document.documentElement.scrollTop-= document.documentElement.scrollTop / 100;}}// 或者使用遞歸gotop.onclick = goTop;function goTop(){console.log("a:" + document.documentElement.scrollTop);if(document.documentElement.scrollTop == 0)return;document.documentElement.scrollTop -= 10;setTimeout(goTop,1);}示例:判定用戶是否閱讀過文本,如:<style>.registration{width: 600px; height: 200px; padding: 10px;border: 2px solid purple; border-radius: 5px;overflow-y: scroll;}</style><h1>同意協(xié)議</h1><div class="registration"><p>Lorem more...</p></div><p><input type="checkbox" name="accept" id="agree" /><label for="agree">我同意</label><input type="submit" id="nextstep" value="http://www.wokk.cn/下一步" /></p><script>window.onload = function(){var registration = document.querySelector(".registration");var agree = document.getElementById("agree");agree.disabled = true;var nextstep = document.getElementById("nextstep");nextstep.disabled = true;var readed = false;var noticeBox = document.createElement("h2");noticeBox.id = "notice";noticeBox.innerText = "請閱讀以下內(nèi)容"registration.parentNode.insertBefore(noticeBox, registration);registration.onscroll = function(e){if(readed) return;readed = this.scrollHeight - this.scrollTop === this.clientHeight;agree.disabled = nextstep.disabled = !readed;noticeBox.innerText = readed ? "歡迎參加" : "請繼續(xù)閱讀";}}</script>示例:滾動(dòng)文本,如:<style>*{margin: 0; padding: 0;}#scrollBox{padding:10px;margin:100px auto;width: 300px; height: 150px; background: lightgray;overflow: hidden;}</style><div id="scrollBox"><ul id="con1"><li>HTML</li><li>CSS</li><li>Javascript</li><li>更多的li</li><li>更多的li</li><li>更多的li</li><li>更多的li</li><li>更多的li</li></ul><ul id="con2"></ul></div><script>var scrollBox = document.getElementById("scrollBox");var con1 = document.getElementById("con1");var con2 = document.getElementById("con2");con2.innerHTML = con1.innerHTML;function scrollUp(){if(scrollBox.scrollTop >= con1.offsetHeight)scrollBox.scrollTop = 0;elsescrollBox.scrollTop++;}var timer = setInterval(scrollUp, 50);scrollBox.onmouseover = function(){clearInterval(timer);};scrollBox.onmouseout = function(){timer = setInterval(scrollUp, 50);}</script>圖示匯總各個(gè)屬性:
文章插圖
元素坐標(biāo)、幾何尺寸
windows對象的pageXOffset、pageYOffset和scrollX、scrollY:
pageXOffset 和 pageYOffset 屬性返回文檔在窗口左上角水平和垂直方向滾動(dòng)的像素;這一對屬性等于scrollX和scrollY屬性,前者是后者的別稱;但I(xiàn)E不支持后者;這些屬性是只讀的;
window.scrollBy(100,200);console.log(window.pageXOffset);console.log(window.pageYOffset);console.log(window.scrollX);console.log(window.scrollY);console.log(window.pageXOffset == window.scrollX); // true與scrollLeft和scrollTop關(guān)系:返回值是一樣的;window.scroll(100,300);console.log(window.pageXOffset);console.log(window.pageYOffset);console.log(document.documentElement.scrollLeft);console.log(document.documentElement.scrollTop);為了跨瀏覽器兼容性,一般使用window.pageXOffset代替window.scrollX;另外,舊版本的 IE(<9)兩個(gè)屬性都不支持,必須通過其他的非標(biāo)準(zhǔn)屬性來解決此問題;window.scrollBy(100,200);var x = (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft;var y = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;console.log(x,y);// 或者var isCSS1Compat = document.compatMode === "CSS1Compat";var x = window.pageXOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;var y = window.pageXOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;console.log(x,y);封裝一個(gè)函數(shù):// 以一個(gè)對象的x和y屬性的方式返回滾動(dòng)條的偏移量function getScrollOffset(w){// 使用指定的窗口,如果不帶參數(shù)則使用當(dāng)前窗口w = w || window;if(w.pageXOffset != null) return {x: w.pageXOffset, y: w.pageYOffset};var d = w.document;if(document.compatMode == "CSS1Compat")return {x: d.documentElement.scrollLeft, y: d.documentElement.scrollTop};// 針對怪異模式return {x: d.body.scrollLeft, y: d.body.scrollTop};}console.log(getScrollOffset().x);console.log(getScrollOffset().y);4. 確定元素大?。?瀏覽器為每個(gè)元素都提供了一個(gè)
Element.getBoundingClientRect()([?ba?nd??] 邊界)方法;該方法是在IE5引入的;該方法不需要參數(shù) , 返回一個(gè)矩形對象,類型為DOMRect,包含6個(gè)屬性:x、y、left、top、right、bottom、width和height;這些屬性給出了元素在頁面中相對于視口的位置和寬高;其中,x和left相同 , y與top相同;right和bottom屬性表示元素的右下角的x和y坐標(biāo);
<div id="mydiv" style="width: 200px;height:100px;background-color:red; ">id is mydiv</div><div style="width: 2000px; background-color: purple;">div</div><script>var mydiv = document.getElementById("mydiv");var rect = mydiv.getBoundingClientRect();console.log(rect);rect = document.documentElement.getBoundingClientRect();console.log(rect);</script>IE并沒有實(shí)現(xiàn)x和y;DOMRect 中的 top, left, right, bottom 屬性是使用對象的其他屬性的值來計(jì)算獲得的;
在IE及老款的Edge中 , 該方法返回的并不是DOMRect類型,而是ClientRect類型;
console.log(ClientRect);console.log(ClientRect.prototype);// [object ClientRectPrototype]getBoundingClientRect()返回的數(shù)據(jù)是包括元素的border及padding;<div id="mydiv" style="width: 200px;height:100px;background-color:red; border:20px solid black;">name is mydiv</div>// …var rect = mydiv.getBoundingClientRect();console.log(rect);這是標(biāo)準(zhǔn)盒子,如果是怪異盒子 , 比如在CSS中設(shè)置box-sizing:border-box,那么返回的數(shù)據(jù)中的寬和高就等于元素的width和height;如果要轉(zhuǎn)化為文檔坐標(biāo) , 需要加上滾動(dòng)的偏移量;
window.scrollBy(50,100);var mydiv = document.getElementById("mydiv");var rect = mydiv.getBoundingClientRect();var x = rect.left + document.documentElement.scrollLeft;var y = rect.top + document.documentElement.scrollTop;// 或者使用上面定義的getScrollOffset()函數(shù)var offsets = getScrollOffset();var x = rect.left + offsets.x;var y = rect.top + offsets.y;console.log(x,y);在布局中,文檔中的元素分為塊盒和行盒,塊盒總是為矩形,但行盒可能跨了多行,因此可能由多個(gè)矩形組成,可以把它稱為邊界矩形;var span = document.getElementById("mydiv").getElementsByTagName("span")[0];var rect = span.getBoundingClientRect();console.log(rect);在IE8及以下瀏覽器中,該方法返回的對象中并不包括width和height屬性;可以使用一個(gè)簡便的方式計(jì)算元素的width和height屬性:var mydiv = document.getElementById("mydiv");var rect = mydiv.getBoundingClientRect();var w = rect.width || (rect.right - rect.left);var h = rect.height || (rect.bottom - rect.top);console.log(w,h);示例:元素在頁面上的相對文檔的偏移量 , 如:function getOffset(ele){if (!ele || ele.nodeType != 1)return;var rect = ele.getBoundingClientRect(),doc = ele.ownerDocument.documentElement;return {top: rect.top + window.pageYOffset - doc.clientTop,left: rect.left + window.pageXOffset - doc.clientLeft};}getClientRects()方法:該方法返回一個(gè)指向客戶端中每一個(gè)盒子的邊界矩形的矩形集合;該矩形集合是一個(gè)只讀的類數(shù)組對象DOMRectList , 可以稱為矩形列表對象 , 它的每個(gè)元素都是DOMRect對象;
var span = document.getElementsByTagName("span")[0];var rects = span.getClientRects();console.log(rects);for(var i=0,len=rects.length; i<len; i++){console.log(rects[i]);}當(dāng)然,該方法也可以應(yīng)用在塊盒中,此時(shí)它只返回包含一個(gè)元素的集合對象;var mydiv = document.getElementById("mydiv");console.log(mydiv.getClientRects()[0]);在IE中返回的是ClientRectList類型,其中保存的是ClientRect類型的對象;對于HTML area元素、自身不做任何渲染的SVG元素、display:none元素和不直接渲染出來的任何元素,都將會(huì)返回一個(gè)空列表;
小示例:
<style>div{display: inline-block; width: 150px;}div p,ol,table{border: 1px solid blue;}span, li, th, td{border: 1px solid green;}</style><div><strong>原始</strong><p><span>Web前端開發(fā)課程 , 包括HTML、CSS、Javascript等內(nèi)容</span></p></div><div><strong>p的rect</strong><p class="rect"><span>Web前端開發(fā)課程,包括HTML、CSS、Javascript等內(nèi)容</span></p></div><div><strong>span的rect</strong><p class="rect"><span>Web前端開發(fā)課程,包括HTML、CSS、Javascript等內(nèi)容</span></p></div><hr /><div><strong>原始</strong><ol><li>HTML</li><li>CSS</li></ol></div><div><strong>ol的rect</strong><ol class="rect"><li>HTML</li><li>CSS</li></ol></div><div><strong>li的rect</strong><ol><li class="rect">HTML</li><li class="rect">CSS</li></ol></div><hr/><div><table><caption>原始</caption><thead><tr><th>thead</th></tr></thead><tbody><tr><td>tbody</td></tr></tbody></table></div><div><table class="rect"><caption>table的rect</caption><thead><tr><th>thead</th></tr></thead><tbody><tr><td>tbody</td></tr></tbody></table></div><div><table><caption>td的rect</caption><thead><tr><th class="rect">thead</th></tr></thead><tbody><tr><td class="rect">tbody</td></tr></tbody></table></div><script>function addClientRect(elt){// 為了使邊框?qū)挾扰c矩形寬度一致 , 這里給每個(gè)客戶矩形上方絕對定位一個(gè) div 。// 注意:如果用戶改變大小或者縮放,繪圖將會(huì)重繪 。var rects = elt.getClientRects();for(var i=0, len=rects.length; i<len; i++){var rect = rects[i];// console.log(rect);var overlayDiv = document.createElement("div");overlayDiv.className = "overlay";overlayDiv.style.position = "absolute";overlayDiv.style.border = "1px solid red";var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;overlayDiv.style.margin = overlayDiv.style.padding = "0";overlayDiv.style.top = (rect.top + scrollTop) + "px";overlayDiv.style.left = (rect.left + scrollLeft) + "px";// 希望rect.width作為邊框?qū)挾龋詢?nèi)容寬度減少2pxoverlayDiv.style.width = (rect.width - 2) + "px";overlayDiv.style.height = (rect.height - 2) + "px";document.body.appendChild(overlayDiv);}}var elts = document.querySelectorAll(".rect");for(var i=0,len=elts.length; i<len; i++)addClientRect(elts[i]);</script>對于NodeList等對象 , 它們是實(shí)時(shí)的,但getBoundingClientRect()和getClientRects()所返回的矩形對象或矩形列表對象并不是實(shí)時(shí)的,它們只是調(diào)用方法時(shí)文檔視覺狀態(tài)的靜態(tài)快照,在用戶滾動(dòng)或改變?yōu)g覽器窗口大小時(shí)不會(huì)更新它們;document.elementFromPoint()方法:如果想在指定位置上判定有什么元素,可以使用該方法;參數(shù)需要傳遞x和y坐標(biāo),不需要單位px,該坐標(biāo)是視口坐標(biāo),該方法返回在指定位置的一個(gè)元素;
如果在指定位置有多個(gè)元素,它返回的是里面和最上面的(即CSS的z-index屬性),如果指定的點(diǎn)在視口以外,該方法返回null;
典型的案例是將鼠標(biāo)指針的坐標(biāo)傳遞給它來判斷鼠標(biāo)在哪個(gè)元素上,但是,在鼠標(biāo)事件中的target屬性也包含了這些坐標(biāo)信息 , 所以 , elementFromPoint()方法并不常用;
var div = document.createElement("div");div.id="divone";div.setAttribute("style","width:200px;height:100px;position:absolute;left:50px;top:200px;border:solid 5px;");document.documentElement.appendChild(div);var innerDiv = document.createElement("div");innerDiv.setAttribute("style","background-color:purple; width:100px; height:50px;");div.appendChild(innerDiv);var elt = document.elementFromPoint(100,200);console.log(elt);console.log(div.getBoundingClientRect());// 鼠標(biāo)事件中的坐標(biāo)var mydiv = document.getElementById("mydiv");document.addEventListener("click",function(e){console.log(e.target);console.log(e.clientX, e.clientY);},false);document.elementsFromPoint()方法:該方法返還在特定坐標(biāo)點(diǎn)下的HTML元素?cái)?shù)組;IE與老版的Edge并不支持;var elts = document.elementsFromPoint(100,250);console.log(elts);滾動(dòng):Window.scroll()、Window.scrollBy()、Window.scrollTo()及Element.scroll()、Element.scrollBy()、Element.scrollTo();
scroll(x, y)或scrollTo(x, y)方法:
var btn = document.querySelector(".btn");btn.onclick = function(){var documentHeight = document.documentElement.offsetHeight;var viewportHeight = window.innerHeight;// 滾動(dòng)到最后一屏window.scrollTo(0, documentHeight - viewportHeight);}scrollBy(x, y)方法:其與以上兩個(gè)方法類似 , 但是它的參數(shù)是相對的,并在當(dāng)前滾動(dòng)的偏移量上增加
window.scrollBy(5,5);示例,閱讀文章時(shí)自動(dòng)滾屏,如:<style>.autoscrollbtn{width: 50px; height: 50px; background-color: purple;position: fixed; top:100px; right: 100px; color:#FFF}</style><div>lorem</div><div class="autoscrollbtn">滾</div><script>// 3874 4531var btn = document.querySelector(".autoscrollbtn");var timer;var viewportHeight = window.innerHeight;var stop = false;btn.addEventListener("click",function(e){if(!stop){e.target.innerText = "停";timer = setInterval(function(){if((viewportHeight + document.documentElement.scrollTop) >=document.documentElement.offsetHeight)clearInterval(timer);scrollBy(0,2);},200);}else{e.target.innerText = "滾";clearInterval(timer);}stop = !stop;});</script>以上方法,參數(shù)除了x和y坐標(biāo)外,還可以是一個(gè)ScrollToOptions對象;CSSOM View 規(guī)范的ScrollToOptions對象,用于指定一個(gè)元素應(yīng)該滾動(dòng)到哪里,以及滾動(dòng)是否應(yīng)該平滑;與我們之前講的scrollIntoView()方法的參數(shù)類似,但類型不一樣,其為ScrollIntoViewOptions , 屬性為block及inline等;而ScrollToOptions對象擁有的是top、left和behavior屬性,其中behavior屬性值可能為:auto及smooth;該參數(shù)IE和Edge不支持;
如果不使用ScrollToOptions對象參數(shù),也可以使用CSS指定,如:
html,body{scroll-behavior:smooth;}但I(xiàn)E和Edge依然不支持;var btn = document.getElementById("btn");btn.addEventListener("click",function(e){window.scroll(mydiv.offsetLeft,mydiv.offsetTop);// 或,但I(xiàn)E與Edge不支持window.scroll({left:mydiv.offsetLeft, top:mydiv.offsetTop, behavior:"smooth"});},false);Element.scroll()、Element.scrollBy()、Element.scrollTo();這些方法是用于在給定的元素中滾動(dòng)到某個(gè)特定坐標(biāo),其用法與window上的三個(gè)方法一致,但I(xiàn)E與Edge均不支持Element的方法;<div id="mydiv" style="background-color: purple; width: 300px; height: 400px; overflow-y: scroll;">Lorem</div><script>var mydiv = document.getElementById("mydiv");mydiv.scroll(0,300);</script>
文章插圖
Web前端開發(fā)之Javascript
以上關(guān)于本文的內(nèi)容,僅作參考!溫馨提示:如遇健康、疾病相關(guān)的問題,請您及時(shí)就醫(yī)或請專業(yè)人士給予相關(guān)指導(dǎo)!
「愛刨根生活網(wǎng)」www.malaban59.cn小編還為您精選了以下內(nèi)容,希望對您有所幫助:- Gucci品牌簡介 gucci是什么牌子
- gucci是古馳品牌 gucci是什么牌子
- 泰拉瑞亞妖刀村正獲取方法詳解
- 為什么教不好自己的孩子 15歲女兒補(bǔ)課與父親發(fā)生爭執(zhí)
- puma是什么品牌? puma是什么牌子
- Furla這個(gè)品牌在輕奢界是什么地位? furla是什么檔次的牌子
- 緬甸一男子撿到一塊黃翡原石 緬甸的翡翠原石價(jià)格
- 燈具這樣選不踩坑! 客廳燈買什么牌子耐用
- 子宮內(nèi)膜炎的癥狀表現(xiàn)是什么 子宮內(nèi)膜炎癥有什么癥狀
- 覆盆子的營養(yǎng)價(jià)值 覆盆子
