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。

原文发布于微信公众号 - HTML5学堂(h5course-com)

原文发表时间:2016-07-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏谦谦君子修罗刀

RN手势

React Native框架底层的手势响应系统提供了响应处理器,PanResponder API将这些手势响应处理器再次进行封装,便于开发者对手势进行处理。 ...

27312
来自专栏全沾开发(huā)

总结CSS3新特性(Animation篇)

总结CSS3新特性(Animation篇) 动画(Animation),是CSS3的亮点.//之一 通过animation属性指定@k...

3076
来自专栏Coding迪斯尼

VUE+WebPack游戏设计:&#39;乘法防线&#39;游戏设计

982
来自专栏程序你好

CSS: :before and :after 使用

693
来自专栏非著名程序员

基础篇章:关于 React Native 之 DrawerLayoutAndroid 组件的讲解

看名字我们就知道这个组件仅限 Android 平台能用。Android 中的 DrawerLayout 就是一个抽屉导航组件,所以这个组件的功能当然也是一样的。...

1937
来自专栏技术博文

jquery中focus()函数实现当对象获得焦点后自动把光标移到内容最后

当对象获得焦点后,自动把光标移到内容最后,使用focus()函数便可实现,下面有个不错的示例,感兴趣的朋友可以参考下 jquery获取焦点后光标在字符串后,当i...

3637
来自专栏云端架构

【云端架构】前端 css print 用法

说到网页打印,首先想到的便是@media查询(即网页css),通过使用媒体类型print即可解决实际应用的大多数问题,比如实现只打印网页的某部分内容,调整字体大...

4178
来自专栏互联网杂技

前端兼容性问题总结

css兼容性问题 1、标签,不加样式控制的情况下,各自的margin 和padding差异较大。 解决方案:css里 *{margin:0;pad...

3285
来自专栏HTML5学堂

移动端框架 滚动类 iScroll5

HTML5学堂:移动端开发中,经常遇到需要模拟APP的效果header或是footer固定住,里面的内容区域实现滚动。但是对低端手机单纯使用CSS是兼容不了,需...

3469
来自专栏较真的前端

那些暖人心却鲜为人知的CSS属性

1756

扫描关注云+社区