资讯专栏INFORMATION COLUMN

原生js实现offset方法

libxd / 2891人阅读

摘要:通过递归实现递归获取可以考虑使用非终止递归继续递归父节点获取值后退出递归执行通过实现当前为以下直接返回当前节点的时直接返回方法返回元素的大小及其相对于视口的位置。返回值包含了一组用于描述边框的只读属性和,单位为像素。

在为 jTool 提供 offset (获取当前节点位置)方法时, 先后使用了两种方式进行实现, 现整理出来以作记录。
通过递归实现
function offset(element) {
    var offest = {
        top: 0,
        left: 0
    };

    var _position;

    getOffset(element, true);

    return offest;

    // 递归获取 offset, 可以考虑使用 getBoundingClientRect
    function getOffset(node, init) {
        // 非Element 终止递归
        if (node.nodeType !== 1) {
            return;
        }
        _position = window.getComputedStyle(node)["position"];

        // position=static: 继续递归父节点
        if (typeof(init) === "undefined" && _position === "static") {
            getOffset(node.parentNode);
            return;
        }
        offest.top = node.offsetTop + offest.top - node.scrollTop;
        offest.left = node.offsetLeft + offest.left - node.scrollLeft;

        // position = fixed: 获取值后退出递归
        if (_position === "fixed") {
            return;
        }

        getOffset(node.parentNode);
    }
}
// 执行offset
var s_kw_wrap = document.querySelector("#s_kw_wrap");
offset(s_kw_wrap);  // => Object {top: 181, left: 400}
通过ClientRect实现
function offset2(node) {
    var offest = {
        top: 0,
        left: 0
    };
    // 当前为IE11以下, 直接返回{top: 0, left: 0}
    if (!node.getClientRects().length) {
        return offest;
    }
    // 当前DOM节点的 display === "node" 时, 直接返回{top: 0, left: 0}
    if (window.getComputedStyle(node)["display"] === "none") {
        return offest;
    }
    // Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。
    // 返回值包含了一组用于描述边框的只读属性——left、top、right和bottom,单位为像素。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。
    // 返回如{top: 8, right: 1432, bottom: 548, left: 8, width: 1424…}
    offest = node.getBoundingClientRect();
    var docElement = node.ownerDocument.documentElement;
    return {
        top: offest.top + window.pageYOffset - docElement.clientTop,
        left: offest.left + window.pageXOffset - docElement.clientLeft
    };
}
// 执行offset
var s_kw_wrap = document.querySelector("#s_kw_wrap");
offset2(s_kw_wrap);  // => Object {top: 181.296875, left: 399.5}
注意事项

offset2() 函数中使用到了 .getClientRects().getBoundingClientRect() 方法,IE11 以下浏览器并不支持; 所以该种实现, 只适于现代浏览器。

.getClientRects()

返回值是 ClientRect 对象集合(与该元素相关的CSS边框),每个 ClientRect 对象包含一组描述该边框的只读属性——left、top、right 和 bottom,单位为像素,这些属性值是相对于视口的top-left的。

并包含 length 属性, IE11以下可以通过是否包含 length 来验证当前是否为IE11以上版现。

.getBoundingClientRect()

返回值包含了一组用于描述边框的只读属性——left、top、right 和 bottom,单位为像素。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。

.getBoundingClientRect() 与 .getClientRects()的关系
这两个方法的区别与当前的 display 相关, 当 display=inline 时, .getClientRects() 返回当前节点内每一行文本的 ClientRect 对象数组, 此时数组长度等于文本行数。

当 display != inline 时, .getClientRects() 返回当前节点的 ClientRect 对象数组,此时数组长度为1.

.getBoundingClientRect() 总是返回当前节点的 ClientRect 对象, 注意这里是 ClientRect 对象而不是对象数组。

相关API

getClientRects

getBoundingClientRect

提示

以上测试, 可以通过在百度首页执行进行测试, document.querySelect("#s_kw_wrap") 所获取到的节点为百度首页输入框

以上代码是在进行jtool类库编码时实践出来的方式,欢迎star

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

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

相关文章

  • 原生 js && jquery 实现知乎收起答案功能

    摘要:需求很简单,而且和知乎的显示全部收起功能非常相似,但是了一下没有找到类似的,因此决定自己实现一个看了知乎的网页代码。 showImg(https://segmentfault.com/img/remote/1460000008488966);showImg(https://segmentfault.com/img/remote/1460000008488967); Update 20...

    brianway 评论0 收藏0
  • 原生 js && jquery 实现知乎收起答案功能

    摘要:需求很简单,而且和知乎的显示全部收起功能非常相似,但是了一下没有找到类似的,因此决定自己实现一个看了知乎的网页代码。 showImg(https://segmentfault.com/img/remote/1460000008488966);showImg(https://segmentfault.com/img/remote/1460000008488967); Update 20...

    Seay 评论0 收藏0
  • 向Zepto学习关于"偏移"的那些事

    摘要:获得当前元素相对于的位置。返回一个对象含有和当给定一个含有和属性对象时,使用这些值来对集合中每一个元素进行相对于的定位。获取对象集合中第一个元素相对于其的位置。结尾以上就是中与偏移相关的几个的解析,欢迎指出其中的问题和有错误的地方。 前言 这篇文章主要想说一下Zepto中与偏移相关的一些事,很久很久以前,我们经常会使用offset、position、scrollTop、scrollLe...

    hzx 评论0 收藏0

发表评论

0条评论

libxd

|高级讲师

TA的文章

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