1. 程式人生 > 其它 >JavaScript 獲取滑鼠及元素在頁面上的位置

JavaScript 獲取滑鼠及元素在頁面上的位置

HTML5學堂:JavaScript獲取滑鼠的位置,大家會想到clientX/Y等屬性,靈活的獲取滑鼠的位置資訊,能夠便於我們實現各種複雜的頁面互動效果,到底還有哪些屬性可以獲取滑鼠的位置資訊?另外,還有哪些能快速獲取標籤在頁面中的位置資訊?

在書寫一些“拖拽”頁面互動效果,比如常見的拖拽效果、自定滾動條、放大鏡等效果,都需要用到了滑鼠或元素在頁面上的位置資訊。為了能夠快速、靈活的獲取滑鼠位置資訊,今天要帶著大家來接觸的不是利用clientX/Y獲取滑鼠的位置資訊,而是利用了大家可能比較少用的兩個屬性layerX/Y和offsetX/Y,它們與clientX/Y有著很大的差別。另外,也要跟大家分享一個方法,它能快速的獲取元素在頁面上的位置資訊,不同於之前學過的offsetLeft等屬性,它就是——getBoundingClientRect()方法

回顧clientX/Y獲取滑鼠位置的方式

雖然clientX/Y是比較常用的屬性,但是咱們還是再回顧一下吧,方便於區分下面要給大家介紹的屬性。

程式碼例項:

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>HTML5Course - 獨行冰海、夢幻雪冰 | HTML5學堂</title>
    <link rel="stylesheet" href="reset.css">
    <script type="text/javascript" src="jquery-1.8.3.min.js"></script>
    <style>
        .wrap {
            width: 200px;
            height: 200px;
            margin: 50px;
            padding: 40px;
            border: 1px solid blue;
        }
        .outer {
            width: 150px;
            height: 150px;
            background-color: skyblue;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="outer" id="outerBox">
        </div>
    </div>
    <script type="text/javascript">
        var outerEle = document.getElementById('outerBox');
 
        outerEle.onclick = function(e) {
            console.log(e.clientX);
        }
    </script>
</body>
</html>

程式碼解析:

  1. 從程式碼中可以看出,clientX/Y屬性是事件物件(e)裡面的一個屬性;
  2. clientX/Y屬性獲取的滑鼠位置是相對於瀏覽器可視區域的左上角的距離。咱們都知道瀏覽器的可視區域位置是固定的不發生滾動的,所以,clientX/Y屬性獲取的滑鼠位置不會隨頁面滾動而改變;
  3. 相容性:所有瀏覽器都能支援。

可以簡單的對clientX/Y屬性進行概括,它所獲取的滑鼠位置參考的原點就是瀏覽器可視區域的左上角。就是這一點,導致我們使用起來靈活性不高,不是所有頁面互動效果用到的滑鼠位置都是參考瀏覽器可視區域的左上角,有可能是參考自身元素的左上角,那麼clientX/Y屬效能否勝任呢?於是開始“度娘”、“谷哥”……終於發現了兩個不是很起眼的屬性:layerX/Y和offsetX/Y屬性。

layerX/Y和offsetX/Y屬性

這兩個屬性跟clientX/Y屬性一樣,也是事件物件裡面的一個屬性,但是它們有何區別呢?別急,咱們一個一個的來分析

layerX/Y屬性的說明

layerX/Y獲取到的滑鼠位置是參考被觸發元素左上角的距離

outerEle.onclick = function(e) {
    // 處理事件物件相容
    var e = e || window.event;
 
    console.log(e.layerX);
}

在click事件中把e.clientX換成e.layerX,然後進行測試。你是不是有疑問了,想跟堡堡說:我測試出來跟e.clientX沒啥區別啊。沒錯,如果你覺得沒啥區別才是對的。layerX/Y屬性有點坑,如果想讓滑鼠的位置參考的是自身元素的左上角,需要給自身元素設定position(屬性值不能是static | inherit),否則預設參考document文件區域的左上角。

在outer選擇器裡面新增position屬性,具體屬性值根據需求來進行設定

.outer {
    position: relative;
    width: 150px;
    height: 150px;
    background-color: skyblue;
}

新增完了程式碼,再測試一下,是不是達到你想要的效果了~

可是,可是,它的瀏覽器支援程度會讓你有一種淡淡的憂傷,堡堡心理苦,但是堡堡不說~

相容性:IE6/7/8不支援,IE9+和Chrome、Safari、Firefox都支援

友情提醒:在IE10+的瀏覽器,獲取到的滑鼠位置會存在一堆的小數,如39.66999816894531這樣。

我們真的要放棄了IE6/7/8不可,於是來嘗試一下offsetX|Y屬性,看這個屬性會不會更強大?

offsetX/Y屬性的說明

offsetX/Y獲取到滑鼠位置也是參考被觸發元素的左上角

outerEle.onclick = function(e) {
    // 處理事件物件相容
    var e = e || window.event;
 
    console.log(e.offsetX);
}

在click事件中把e.layerX換成e.offsetX,然後進行測試。發現這個屬性還真不錯,還能相容IE6/7/8。

堡堡在網上看到很多部落格中寫道offsetX/Y屬性火狐瀏覽器不支援,但是自己去測試了一下火狐瀏覽器,火狐瀏覽器是可以支援該屬性,並不是網上說的那樣。導致這種狀況發生的原因可能是現在火狐瀏覽器開始支援該屬性了,另外也要告訴大家——實踐是檢驗真理的唯一標準。

相容性:IE和Chrome、Safari均完美支援,Firefox也能支援(具體需要看瀏覽器的版本)

雖然它相容性挺完美的,但是還有一點點的瑕疵。在outer選擇器裡面,設定border,並進行測試,檢視結果。

.outer {
    width: 150px;
    height: 150px;
    border: 10px solid gray;
    background-color: skyblue;
}

如果滑鼠在邊框上觸發會返回負值,內容區以內為正值,換句話說滑鼠位置是參考自身元素內容區域的左上角(不包括border)。

簡要概括這兩個屬性

當觸發元素設定了position屬性(屬性值不能是static | inherit),layerX/Y和offsetX/Y就成為了友好的朋友,基本上相同,唯一不同的是,layerX/Y屬性是以border左上角為原點,offsetX/Y屬性是以內容左上角為原點

用getBoundingClientRect()獲取頁面元素位置資訊

大家估計會經常用到offsetLeft、offsetTop等屬性來獲取元素的尺寸、位置等資訊,想具體瞭解的可以回覆“元素資訊”到HTML5學堂公眾號。

今天要給大家分享的是另外一種快速獲取元素在頁面上的位置,趕緊嘗試書寫一下下面的例項

程式碼例項:

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>HTML5Course - 獨行冰海、夢幻雪冰 | HTML5學堂</title>
    <link rel="stylesheet" href="reset.css">
    <script type="text/javascript" src="jquery-1.8.3.min.js"></script>
    <style>
        .wrap {
            width: 200px;
            height: 200px;
            margin: 50px;
            padding: 40px;
            border: 1px solid blue;
        }
        .outer {
            width: 150px;
            height: 150px;
            border: 10px solid gray;
            background-color: skyblue;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="outer" id="outerBox">
        </div>
    </div>
    <script type="text/javascript">
        // 通過ID的方式獲取標籤
        var outerEle = document.getElementById('outerBox');
 
        console.log(outerEle.getBoundingClientRect());
    </script>
</body>
</html>

程式碼解析:

  1. 使用getBoundingClientRect()方法。它返回一個物件,其中包含了left、right、top、bottom四個屬性,這四個屬性分別代表什麼含義,具體來看下面的分析圖
  1. 相容性:IE、Firefox、Chrome都支援該方法 看到它的支援程度算是挺完美的,但是總會有一點點的瑕疵,在IE中,預設參考原點是從(2,2)開始計算,導致最終距離會比其它瀏覽器多出兩個畫素,因此咱們需要對它進行相容處理了。
  2. 在IE中有一個小問題,在非IE瀏覽器下document.documentElement.clientTop/left值為0,而在在IE中document.documentElement.clientTop/left並不為0,而是2(儘管對html、body設定了margin和padding都為0),所以為了讓getBoundingClientRect()方法相容性更好,在IE中需要減去document.documentElement.clientTop/left的值,這樣就更完美了。

完整程式碼如下

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>HTML5Course - HTML5學堂 | 獨行冰海、夢幻雪冰</title>
    <link rel="stylesheet" href="reset.css">
    <script type="text/javascript" src="jquery-1.8.3.min.js"></script>
    <style>
        .wrap {
            width: 200px;
            height: 200px;
            margin: 50px;
            padding: 40px;
            border: 1px solid blue;
        }
        .outer {
            width: 150px;
            height: 150px;
            border: 10px solid gray;
            background-color: skyblue;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="outer" id="outerBox">
        </div>
    </div>
    <script type="text/javascript">
        var outerEle = document.getElementById('outerBox');
 
        /*
         * [getBoundingClientRect 獲取頁面元素的位置]
         * @param  {[obj]} ele [目標元素]
         * @return {[obj]}     [物件]
         * @author HTML5學堂 | 劉國利、陳能堡
         */
        function getBoundingClientRect(ele) {
            var top     = document.documentElement.clientTop, 
                left    = document.documentElement.clientLeft,
                rect    = ele.getBoundingClientRect();
 
            // document.documentElement.clientTop/Left在IE下獲取到的值為2,非IE獲取到的值為0;
            // 這樣保證在各個瀏覽器的效果都是一致的
 
            // 分別減去多出來的2px
            return {
                top: rect.top - top,
                right: rect.right - left,
                bottom: rect.bottom - top,
                left: rect.left - left
            }
        }
 
        // 呼叫方法
        console.log(getBoundingClientRect(outerEle));
    </script>
</body>
</html>

HTML5學堂小編-堡堡,耗時5h。