详解原生js实现offset方法


Posted in Javascript onJune 15, 2017

在为 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()的关系

  1. 这两个方法的区别与当前的 display 相关, 当 display=inline 时, .getClientRects() 返回当前节点内每一行文本的 ClientRect 对象数组, 此时数组长度等于文本行数。
  2. 当 display != inline 时, .getClientRects() 返回当前节点的 ClientRect 对象数组,此时数组长度为1.
  3. .getBoundingClientRect() 总是返回当前节点的 ClientRect 对象, 注意这里是 ClientRect 对象而不是对象数组。

提示

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

希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
IE中jscript/javascript的条件编译
Sep 07 Javascript
用js实现手把手教你月入万刀(转贴)
Nov 07 Javascript
JavaScript 继承详解(四)
Jul 13 Javascript
JS 参数传递的实际应用代码分析
Sep 13 Javascript
js读取配置文件自写
Feb 11 Javascript
jQuery学习笔记之jQuery中的$
Jan 19 Javascript
JavaScript实现动画打开半透明提示层的方法
Apr 21 Javascript
JavaScript实现的原生态兼容IE6可调可控滚动文字功能详解
Sep 19 Javascript
浅谈angular4.0中路由传递参数、获取参数最nice的写法
Mar 12 Javascript
vue下拉列表功能实例代码
Apr 08 Javascript
React降级配置及Ant Design配置详解
Dec 27 Javascript
基于纯JS实现多张图片的懒加载Lazy过程解析
Oct 14 Javascript
微信小程序 监听手势滑动切换页面实例详解
Jun 15 #Javascript
微信小程序canvas写字板效果及实例
Jun 15 #Javascript
AngularJs实现聊天列表实时刷新功能
Jun 15 #Javascript
bootstrap daterangepicker双日历时间段选择控件详解
Jun 15 #Javascript
详解react-router如何实现按需加载
Jun 15 #Javascript
jQuery实现 RadioButton做必选校验功能
Jun 15 #jQuery
bootstrap daterangepicker汉化以及扩展功能
Jun 15 #Javascript
You might like
如何解决PHP使用mysql_query查询超大结果集超内存问题
2016/03/14 PHP
php 使用expat方式解析xml文件操作示例
2019/11/26 PHP
Javascript hasOwnProperty 方法 & in 关键字
2008/11/26 Javascript
解决jquery版本冲突的有效方法
2014/09/02 Javascript
js实现点击添加一个input节点
2014/12/05 Javascript
node.js中的fs.renameSync方法使用说明
2014/12/16 Javascript
浅析JavaScript事件和方法
2015/02/28 Javascript
浅谈$(document)和$(window)的区别
2015/07/15 Javascript
[原创]Javascript 实现广告后加载 可加载百度谷歌联盟广告
2016/05/11 Javascript
20分钟成功编写bootstrap响应式页面 就这么简单
2016/05/12 Javascript
jQuery简单实现仿京东分类导航层效果
2016/06/07 Javascript
原生JS实现在线问卷调查投票特效
2017/01/03 Javascript
node.js的事件机制
2017/02/08 Javascript
BootStrap 弹出层代码
2017/02/09 Javascript
bootstrap警告框示例代码分享
2017/05/17 Javascript
JS+HTML5实现图片在线预览功能
2017/07/22 Javascript
微信小程序常用简易小函数总结
2019/02/01 Javascript
移动端(微信等使用vConsole调试console的方法
2019/03/05 Javascript
js实现图片区域可点击大小随意改变(适用移动端)代码实例
2019/09/11 Javascript
React Ant Design树形表格的复杂增删改操作
2020/11/02 Javascript
使用python 获取进程pid号的方法
2014/03/10 Python
wxPython事件驱动实例详解
2014/09/28 Python
Python通过OpenCV的findContours获取轮廓并切割实例
2018/01/05 Python
Python 数据库操作 SQLAlchemy的示例代码
2019/02/18 Python
python输出电脑上所有的串口名的方法
2019/07/02 Python
Python模块_PyLibTiff读取tif文件的实例
2020/01/13 Python
opencv 实现特定颜色线条提取与定位操作
2020/06/02 Python
美国狗旅行和户外用品领先供应商:kurgo
2020/08/18 全球购物
泰国排名第一的家居用品中心:HomePro
2020/11/18 全球购物
杠杆的科学教学反思
2014/01/10 职场文书
学生周末回家住宿长期请假条
2014/02/15 职场文书
体育活动总结范文
2014/05/04 职场文书
2014年四风问题个人对照自查剖析材料
2014/09/15 职场文书
幼儿园教师个人工作总结2015
2015/05/12 职场文书
血轮眼轮回眼特效 html+css
2021/03/31 HTML / CSS
浅谈mysql哪些情况会导致索引失效
2021/11/20 MySQL