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 条评论
登录 后参与评论

相关文章

来自专栏青蛙要fly的专栏

项目需求讨论 — ConstraintLayout 详细使用教程

关于ConstraintLayout的文章网上一抓一大把,而且ConstraintLayout在16年就已经出来了,但是我一直没有试着去使用(别问我为什么不去使...

902
来自专栏九彩拼盘的叨叨叨

学习纲要:常见标签和属性

712
来自专栏IMWeb前端团队

animation动画实践

由于业务关系,有幸参与腾讯课堂app下载页面制作,原则上ie8、9可表现为静态版本,而高级浏览则为动画版本。在这把一些重要思想和中间遇到的一些问题记录下,以供知...

1890
来自专栏進无尽的文章

绘图-视图遮罩MaskView的使用

可以这样理解,是将maskView每个point的alpha赋值给View的重叠部分相对应的point,这样view的重叠每个point都有个alpha值了,v...

912
来自专栏web前端

制作H5响应式页面注意事项、微信二次分享

1、H5页面(APP端)      1.1     APP端页面用HTML5制作,头部需要加适配信息:   <meta http-equiv="Content-...

2749
来自专栏web前端

制作H5响应式页面注意事项、微信二次分享

          1.2.1     重要的图片用img标签(例如头部banner等包含特定信息的内容图片),不重要的底板用背景形式显示,例如底部背景

1300
来自专栏林德熙的博客

WPF 在 DrawingContext 的 push 如何使用

如果在一个 DrawingContext 画出一个 DrawingVisual ,如何修改这个 DrawingVisual 的大小,对他进行变换?

371
来自专栏守候书阁

也许vue+css3做交互特效更简单

做项目就难免会开发交互效果或者特效,而我最近开发的项目一直在使用vue,开发技术栈方面,理所当然就使用了vue+css3开发,过程中发现使用vue+css3开发...

942
来自专栏腾讯AlloyTeam的专栏

移动端输入框填坑系列(一)

输入在移动端是一个很常用的功能,那么输入框必然是一个很重要的部分。然而,移动端输入框总会遇到各种各样的问题,无论是样式还是ios和android两端体验不一致都...

1.5K0
来自专栏欧阳大哥的轮子

iOS界面布局的核心以及TangramKit介绍

TangramKit是iOS系统下用Swift编写的第三方界面布局框架。他集成了iOS的AutoLayout和SizeClass以及Android的五大容器布局...

943

扫码关注云+社区