资讯专栏INFORMATION COLUMN

document.elementFromPoint

fredshare / 2774人阅读

摘要:除了坐标问题外,该方法只能返回顶层元素,也就是在有个元素重叠的情况下,只能返回最上层的元素。

先说一下这个方法的参数

elemntFromPoint(x,y);//传入坐标值,返回当前页面上包含该坐标点的顶层元素

注意2点,坐标值和顶层元素

先说坐标,因为不同的人理解是不一样的,也就造就了这个方法在不同的浏览器中表现是不一样的,所以在传入坐标时就分 整体页面坐标 和 可视区域坐标,我们看上篇文章中的图来理解下:

中间的方块是可视区域,红点相对可视区域的左上角我们称之为 clientX和clientY,相对于页面起始处的左上角称之为 pageX和pageY

有的浏览器在调用elementFromPoint时要求传入clientX和clientY而有的要求pageX和pageY,具体的详见:http://www.quirksmode.org/webkit.html 看 elementFromPoint部分,上面也提到如果在标准中进行规则统一,也会规定使用可视区域的坐标

显然我们如果要用这个方法时,就要注意兼容了,而对于同一种浏览器,因为版本的不同,导致同样的这个方法可能要求传入的坐标也不同,比如chrome浏览器,那么,我们该如何去兼容呢?

The w3c specification says:

The elementFromPoint(x, y) method, when invoked, must return the element at coordinates x,y in the viewport. The element to be returned is determined through hit testing. If either argument is negative, x is greater than the viewport width excluding the size of a rendered scroll bar (if any), or y is greater than the viewport height excluding the size of a rendered scroll bar (if any), the method must return null. If there is no element at the given position the method must return the root element, if any, or null otherwise.

调用elementFromPoint时,必须传入可视区域内的坐标,如果你传入的坐标不在可视区域内,即使在这个坐标处有元素,也将返回null;我们可以根据这个特性来写兼容代码:

使用jq实现的代码如下,我们可以很方便的改写成自已的

(function($) {
    var check = false,
        isRelative = true;
    $.elementFromPoint = function(x, y) {
        if (!document.elementFromPoint) return null;
        if (!check) {
            var sl;
            if ((sl = $(document).scrollTop()) > 0) {
                isRelative = (document.elementFromPoint(0, sl + $(window).height() - 1) == null);
            } else if ((sl = $(document).scrollLeft()) > 0) {
                isRelative = (document.elementFromPoint(sl + $(window).width() - 1, 0) == null);
            }
            check = (sl > 0);
        }
        if (!isRelative) {
            x += $(document).scrollLeft();
            y += $(document).scrollTop();
        }
        return document.elementFromPoint(x, y);
    }
})(jQuery);

原理就是上面说的,如果页面有滚动,则尝试获取页面坐标最边缘处的元素,如果能获取到,说明是使用页面坐标,因为在有滚动的情况下,获取可视边缘处的坐标,页面坐标会大于可视区域的坐标,所以如果是用可视区域坐标,肯定返回null

嗯,一切看起来都还不错,IE6 7就不行了,仔细看了下这个方法,这个方法最早应该是IE特有的,最后被其它浏览器实现,在IE下,一直使用的是可视区域的坐标,但是在IE6 7的情况下,当你传大于可视区域的坐标时,也是可以获取到值的,也就造成了上面兼容代码无法在IE6 7下正常工作,所以上面的代码并没有考虑IE6 7的情况,需要你添加一些判断。

除了坐标问题外,该方法只能返回顶层元素,也就是在有2个元素重叠的情况下,只能返回最上层的元素。

之前我也有写过高效拖动的文章,比如拖动排序分类,常见的是鼠标在拖动的时候,不停的计算鼠标是在哪个分类上面,然后做出变换的效果,如果列表元素比较少的情况下还是可以的,如果大于1000个,而这些分类的高度不定,通过这个循环判断的方法显示就会觉得很卡

我在之前的文章中提到可以在mousemove时,不让任何元素挡着鼠标(通常我们可能会在拖动时,让被拖动的元素随鼠标一起移动,这时候元素可能挡在鼠标的下方),可通过事件的event.target获取鼠标指向的元素,这样列表中有多少个元素都不会影响到效果

回头说一下setCapture方法,该方法是IE下让元素捕获到事件,比如鼠标移到浏览器外边也可以响应得到,然而这个方法在firefox在4版本时被引进firefox中,引入后如果拖动时你调用了setCapture,就算鼠标下面没有东西挡着,event.target也始终是鼠标按下时的target,IE中则不是,调用setCapture后,mousemove时依然可以获取到,当然IE下可能要用event.srcElement获取

所以,保险起见,我们要调用setCapture,而调用后,firefox4以后又不能及时获取到鼠标下的元素,抛开这些,在ios设备上,touchmouse时,同样也是获取不到手指指向的元素,所以只好回头折腾这个elementFromPoint了。

在折腾这些的时候,还发现诸如getBoundingClientRect在ios设备上也是有问题的,这个方法正常返回相对可视区域的坐标,而在ios上,实现的却是相对页面的坐标,实在让人郁闷

回头再看一下兼容,之前做浏览器间的兼容,更多的是这个浏览器有这个方法,那个浏览器有那个方法,方法的不同而已,现在的兼容则是同样的方法,最终的结果不同,比如setCapture还有getBoundingClientRect等,可能还有其它一些有问题的方法,这种兼容起来更麻烦,远不如没有方法来的干脆些。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87847.html

相关文章

  • js获取文档和元素的坐标

    摘要:例如我想知道写文章的这个页面中定时发布的按钮的尺寸和位置获取宽度,高度的另一种方式对于内联元素调用,返回的是边界矩形,因为内联元素可能跨了多行,所以可能是由多个矩形组成的。对于分为两行的内联元素,边界矩形就包含了两行的宽度。 这两天在写瀑布流的实现,使用了一些关于获取文档坐标、元素位置的函数,刚好看到犀牛书上关于这部分的介绍,特写此文章进行总结,方便日后查找使用。 文档坐标和视口坐标 ...

    wanglu1209 评论0 收藏0
  • js获取文档和元素的坐标

    摘要:例如我想知道写文章的这个页面中定时发布的按钮的尺寸和位置获取宽度,高度的另一种方式对于内联元素调用,返回的是边界矩形,因为内联元素可能跨了多行,所以可能是由多个矩形组成的。对于分为两行的内联元素,边界矩形就包含了两行的宽度。 这两天在写瀑布流的实现,使用了一些关于获取文档坐标、元素位置的函数,刚好看到犀牛书上关于这部分的介绍,特写此文章进行总结,方便日后查找使用。 文档坐标和视口坐标 ...

    MSchumi 评论0 收藏0
  • 爬虫可视化点选配置工具之获取鼠标点选元素

    摘要:类型指定可能被其他元素包含的后代元素。这样页面选择函数就写完了,下面就是引用了,在中添加函数点击以上就完成了页面选择功能 前言 前面两章已经介绍怎么开发一个chrome插件和怎么使用vue搭建一个弹出框的chrome插件,这一章来实现页面元素选择的功能,效果如下图,鼠标放到元素上,元素会高亮: showImg(https://segmentfault.com/img/bVbilIx?w...

    leoperfect 评论0 收藏0
  • 关于DOM的问题笔记

    摘要:实时可以传参返回包括了所有名字符合指定条件的元素实时可以传参用于选择拥有属性的元素比如和等返回匹配指定属性的元素节点。返回位于页面指定位置最上层的子节点。此外,使用可以防止攻击。而自身不在存在于创建它时所在的位置。 1. 获取某个 dom 元素的方式 //节点集合属性(元素节点选取) document.all //返回文档中所有元素 document.links //返回当前文...

    FullStackDeveloper 评论0 收藏0
  • 原生JS中DOM节点相关API合集

    摘要:返回一个个比特位的二进制值,表示参数节点和当前节点的关系返回布尔值,用于检查两个节点是否相等。生成一个对象事件方法生成一个事件对象,该对象能被方法使用注册事件注销事件触发事件其他返回一个布尔值,表示当前文档之中是否有元素被激活或获得焦点。 节点属性 Node.nodeName //返回节点名称,只读Node.nodeType //返回节点类型的常数值,只读Node.nodeVa...

    lemon 评论0 收藏0

发表评论

0条评论

fredshare

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<