javascript快速入門19--定位

水之原發表於2013-12-01

元素尺寸

獲取元素尺寸可以使用下面幾種方式

  • 元素的style屬性width,height,但這些屬性往往返回空值,因為它們只能返回使用行內style屬性定義在元素上的樣式
  • 元素的currentStyle屬性width,height(IE),getComputedStyle(obj,null)返回物件的width,height,這樣可以獲取元素的實際CSS定義的寬度和高度,但當元素沒有使用CSS定義外觀時,雖然元素仍然有大小(只要其中有字元或其它元素),這些屬性的返回值是不確定的,如IE返回auto,而火狐則返回一個看似理想的值。
  • 物件的clientWidth和clientHeight屬性給出元素的可視部分的寬度和高度,當有滾動條時,只返回可見區域大小,對於塊級元素,將返回元素的所設定的寬度和高度加上填充(padding),這一點幾乎所有瀏覽器都達成一致.但當塊級元素並沒有設定寬和高以及填充時,就出現不同了,谷歌瀏覽器和火狐瀏覽器的報告一致,IE報告都為0,而Opera則有所偏差.再將這兩個屬性應用到行內元素上,IE和火狐都報告為0,谷歌報告了一個看似理想的數字,而Opera竟會一個為正另一個負!
  • 物件的offsetWidth和offsetHeight屬性用來取得物件在頁面中的實際所佔區域大小(所設定的寬高加邊框加填充,當有滾動條時還會算上滾動條),似乎這個屬性對於設定了寬和高的塊級元素幾乎沒有什麼瀏覽器相容問題,但不得不說的是火狐的一個BUG.火狐瀏覽器有個可將頁面放大縮小的功能,當將頁面縮小後,物件的offsetWidth和offsetHeight屬性會發生細微的變化-變小几畫素!儘管這對JS程式設計來講幾乎沒影響,但似乎這個BUG也太明顯了.這兩個屬性變非總是那麼讓人信任,當物件並沒設定寬高或它是一個行內元素時,它的報告就顯得相當複雜,不同瀏覽器都有自己一套標準(但是仍然可以肯定的是這兩個屬性報告的仍然是該元素佔據的的空間大小,只不過會因字型和空格的預設大小不同而不同),最讓人摸不著頭腦的是Opera,對於一個body的子塊級元素,當body和它自身沒設定寬高時,Opera報告的它的寬度相當大,6千多畫素!
  • 還有就是scrollWidth和scrollWidth了,就目前來講,對於一個沒有滾動條和溢位的元素,其它瀏覽器對這個屬性的報告還算有規律:物件的clientWidth+border=scrollWidth.物件的clientHeight+border=scrollHeight;只有IE報告有問題!它以元素中的內容為準,如果元素內沒有其它內容,雖然IE並不會報0,但會報告一個非常小的值!再看看當元素有滾動條時怎麼樣吧!唯一值得高興的是,它們對有滾動條的元素的clientWidth和clientHeight都報告一致(但仍有一點要注意,那就是火狐的一BUG,頁面縮放功能帶來的鬱悶,而且這次變化非常大).而對於scrollWidth和scrollHeight真是五花八門:先說好的,儘管各不一樣,但它們對scrollWidth不知為什麼,相差不大,那麼壞的就是,scrollHeight屬性就相差太大了,沒規律可循!(scrollWidth和scrollHeight屬性返加物件內容的實際所需空間,當元素設定了overflow值為scroll或hidden之類時,scrollWidth和scrollHeight屬性就派上用場了,可惜的是它問題太多了)

綜上所述,對於一個在CSS中定義了大小的塊級元素,獲取它的實際大小是很簡單的,但對於沒有定義寬度和高度,或是一行內元素時,則沒有跨瀏覽器的解決方案可以獲取它的實際大小!

視窗視口寬度和高度

對於視窗視口(視口指顯示頁面的那部分)的大小,Mozilla提供了window.innerWidth與window.innerHeight兩個屬性,而IE則沒有相對應的屬性,但可以使用document.documentElement.clientWidth與document.documentElement.clientHeight 兩個屬性來獲取!另外,對於IE6之前的版本,則需要使用document.body的clientWidth與clientHeight屬性!

    //獲取視口大小,依次為火狐,IE6及IE6以上的版本,IE6以下的版本
    var w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    var h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
    //事實上,IE版本低於6的瀏覽器幾乎不存在了
    //而同時其實火狐也支援通過document.documentElement的clientWidth,clientHeight屬性獲取視口大小
    //完全可以不做任何瀏覽器檢測
    w = document.documentElement.clientWidth;
    h = document.documentElement.clientHeight;

 

元素邊框寬度

獲取元素邊框寬度可以使用下面幾種方式

  • 元素style屬性的borderWidth,但同樣它只能返回使用HTML行內style屬性定義的邊框樣式
  • 使用currentStyle屬性或getComputedStyle方法,可以獲取元素CSS定義的實際邊框樣式,如果CSS沒有定義元素的邊框,一般的元素是沒有邊框的,但部分元素,如表單控制元件,仍然具有預設的邊框寬度!對於此類情況,也是不能依靠這種方法來獲取元素的邊框大小的!
  • 物件的clientLeft和clientTop屬性。不能不說clientLeft和clientTop的名字起的太奇怪了,事實上它們的名字更應該這樣:clientBorderLeftWidth和clientBorderTopWidth(難道是太長了的原因?);更奇怪的是,它們只能取得設定在元素上的左邊框和上邊框的粗細,而沒有返回右邊和下邊的邊框寬度的屬性!另外,對於文件根元素(documentElement),在IE中它有預設的兩畫素邊框寬度,而其它瀏覽器中報告為0.

元素座標

獲取元素座標方法:

  • 元素style屬性的left,top屬性,不但這種方法僅適用於使用HTML style屬性宣告樣式的元素,並且只有當元素使用定位(position設定為relative,absolute,fixed,但不包含static)時,才會存在這些值
  • 元素currentStyle屬性或getComputedStyle方法返回的Style物件的left,top屬性,但這種方法僅對採用定位的元素有作用
  • 元素的offsetLeft與offsetTop屬性返回元素在頁面中相對於父元素的座標。一般對於進行了定位的元素(即position為不是static的值或沒有設定),這兩個屬性的返回值為CSS中定義的元素的left,top值,當其自身有邊距時(margin),還會加上邊距。而對於沒有采用定位的元素則顯得比較複雜,我們只能考慮下設定了寬度和高度的塊級元素,因為沒有設定寬高,及行內元素,沒有辦法獲取它的寬高,即使能獲取它的left,top值也顯得無意義了。對於沒有采用定位的塊級元素,offsetLeft與offsetTop屬性將返回其自身的margin+父元素的padding。元素還有個offsetParent屬性返回元素的相對定位的父元素,當使用定位時,各個瀏覽器一致,並且和CSS裡設定的吻合,當不使用定位時,父元素是WHO成了問題,各個瀏覽器認識不一樣,IE報告為其父節點,而其它瀏覽器則報告為body,當然,這次IE正確了。另外,對於表格中的一些元素,不應對其進行定位!

具有滾動條時的定位

scrollLeft和scrollTop,它們用來獲得那些具有滾動條的元素滾動條滾動的距離,而沒有滾動條的元素,它總返回0.可以這樣認為,這兩個屬性報告了有滾動條元素中未顯示的左一部分的寬(scrollLeft)和上一部分的高(scrollTop).而對於頁面的滾動條,則取documentElement的scrollLeft與scrollTop屬性,但是對於谷歌瀏覽器,它會將頁面的滾動條視為document.body的!

Event物件與定位相關的屬性

clientX與clientY返回事件發生時滑鼠在視口中的座標;offsetX與offsetY返回事件發生時滑鼠相對於目標物件的座標,以目標物件右上角為座標原點,而這兩個屬性的W3C DOM版本則為layerX與layerY;pageX與pageY返回事件發生時滑鼠相對於頁面的座標,雖然這個屬性IE不支援,但仍然有補救的餘地!

    //不要在每個事件處理函式中進行判斷,而要善於利用之前的fixEvent函式!
    function fixEvent(evt) {
        if (!evt.target) {
            //函式中已有的部分
            evt.pageX = evt.clientX+document.documentElement.scrollLeft;
            evt.pageY = evt.clientY+document.documentElement.scrollTop;
            //可以將事件發生時滑鼠在視口中的座標加上頁面滾動的偏移量得出pageX與pageY
            evt.layerX = evt.offsetX;
            evt.layerY = evt.offsetY;
        }
        return evt;
    }

 

拖動

最簡單的拖動指令碼——拖動的基本原理

    window.onload = function () {
        var oDiv = document.getElementById("oDiv");//oDiv必須使用CSS定位
        oDiv.onmousedown = drag;
        function drag(evt) {
            evt = evt || window.event;
            this.onmouseup = drop;
            this.onmousemove = moveDiv;
            this.offset = {
                x:evt.offsetX || evt.layerX,
                y:evt.offsetY || evt.layerY
            };
        }
        function moveDiv(evt) {
            evt = evt || window.event;
            this.style.left = evt.clientX-this.offset.x+"px";
            this.style.top = evt.clientY-this.offset.y+"px";
        }
        function drop(evt) {
            this.onmouseup = null;
            this.onmousemove = null;
        }
    };

 

相關文章