详解原生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 相关文章推荐
Eclipse去除js(JavaScript)验证错误
Feb 11 Javascript
使用node.js 获取客户端信息代码分享
Nov 26 Javascript
JavaScript 函数的执行过程
May 09 Javascript
javascript三种代码注释方法
Jun 02 Javascript
JS代码实现根据时间变换页面背景效果
Jun 16 Javascript
关于Javascript回调函数的一个妙用
Aug 29 Javascript
Material(包括Material Icon)在Angular2中的使用详解
Feb 11 Javascript
vue.js动画中的js钩子函数的实现
Jul 06 Javascript
javascript使用正则实现去掉字符串前面的所有0
Jul 23 Javascript
JavaScript Window窗口对象属性和使用方法
Jan 19 Javascript
JS中类的静态方法,静态变量,实例方法,实例变量区别与用法实例分析
Mar 14 Javascript
javascript this指向相关问题及改变方法
Nov 19 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语法(1)
2006/10/09 PHP
php Ajax乱码
2008/04/09 PHP
php 随机排序广告的实现代码
2011/05/09 PHP
深入php之规范编程命名小结
2013/05/15 PHP
基于MySQL到MongoDB简易对照表的详解
2013/06/03 PHP
zf框架的数据库追踪器使用示例
2014/03/13 PHP
初识Laravel
2014/10/30 PHP
PHP中shuffle数组值随便排序函数用法
2014/11/21 PHP
phpstorm 配置xdebug的示例代码
2019/03/31 PHP
flash javascript之间的通讯方法小结
2008/12/20 Javascript
解决表单中第一个非隐藏的元素获得焦点的一个方案
2009/10/26 Javascript
javascript学习笔记(七)利用javascript来创建和存储cookie
2011/04/08 Javascript
javascript代码编写需要注意的7个小细节小结
2011/09/21 Javascript
正则表达式搭配js轻松处理json文本方便而老古
2013/02/17 Javascript
主页面中的两个iframe实现鼠标拖动改变其大小
2013/04/16 Javascript
框架页面高度自动刷新的Javascript脚本
2013/11/01 Javascript
jQuery常用操作方法及常用函数总结
2014/06/19 Javascript
Jquery全选与反选点击执行一次的解决方案
2015/08/14 Javascript
jquery实现文本框textarea自适应高度
2016/03/09 Javascript
使用Object.defineProperty实现简单的js双向绑定
2016/04/15 Javascript
原生js实现下拉框功能(支持键盘事件)
2017/01/13 Javascript
微信小程序学习笔记之文件上传、下载操作图文详解
2019/03/29 Javascript
单线程JavaScript实现异步过程详解
2020/05/19 Javascript
详解python多线程、锁、event事件机制的简单使用
2018/04/27 Python
python中itertools模块zip_longest函数详解
2018/06/12 Python
用Python写一个模拟qq聊天小程序的代码实例
2019/03/06 Python
python之MSE、MAE、RMSE的使用
2020/02/24 Python
纯css3显示隐藏一个div特效的具体实现
2014/02/10 HTML / CSS
酒店销售主管岗位职责
2014/01/04 职场文书
九年级物理教学反思
2014/01/29 职场文书
小学生读书感言
2014/02/12 职场文书
团组织推优材料
2014/12/29 职场文书
食品安全责任书范本
2015/05/09 职场文书
2016年度师德标兵先进事迹材料
2016/02/26 职场文书
使用canvas对video视频某一刻截图功能
2021/09/25 HTML / CSS
Three.js实现雪糕地球的使用示例详解
2022/07/07 Javascript