JavaScript 获取鼠标及元素在页面上的位置

时间:2022-05-04
本文章向大家介绍JavaScript 获取鼠标及元素在页面上的位置,主要内容包括回顾clientX/Y获取鼠标位置的方式、layerX/Y和offsetX/Y属性、offsetX/Y属性的说明、简要概括这两个属性、用getBoundingClientRect()获取页面元素位置信息、代码解析:、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

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。