详解原生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 相关文章推荐
Javascript匿名函数的一种应用 代码封装
Jun 27 Javascript
zeroclipboard复制到剪切板的flash
Aug 04 Javascript
javascript里模拟sleep(两种实现方式)
Jan 25 Javascript
用Jquery选择器计算table中的某一列某一行的合计
Aug 13 Javascript
全面了解构造函数继承关键apply call
Jul 26 Javascript
javascript中json基础知识详解
Jan 19 Javascript
jQuery Ajax前后端使用JSON进行交互示例
Mar 17 Javascript
详解vue-cli构建项目反向代理配置
Sep 07 Javascript
Vue-Router实现组件间跳转的三种方法
Nov 07 Javascript
Vue+jquery实现表格指定列的文字收缩的示例代码
Jan 09 jQuery
Swiper.js实现移动端元素左右滑动
Sep 08 Javascript
小程序的上传文件接口的注意要点解析
Sep 17 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可逆加密解密算法实例代码
2014/01/21 PHP
php实现图片添加水印功能
2014/02/13 PHP
Laravel5.1数据库连接、创建数据库、创建model及创建控制器的方法
2016/03/29 PHP
PHP编程 SSO详细介绍及简单实例
2017/01/13 PHP
ecshop添加菜单及权限分配问题
2017/11/21 PHP
laravel框架数据库配置及操作数据库示例
2019/10/10 PHP
JavaScript 字符串与数组转换函数[不用split与join]
2009/12/13 Javascript
jquery刷新页面的实现代码(局部及全页面刷新)
2011/07/11 Javascript
图片img的src不变让浏览器重新加载实现方法
2013/03/29 Javascript
jQuery 获取兄弟元素的几种不错方法
2014/05/23 Javascript
JavaScript简单下拉菜单实例代码
2015/09/07 Javascript
JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome
2017/01/05 Javascript
jQuery实现鼠标悬停3d菜单展开动画效果
2017/01/19 Javascript
二维码图片生成器QRCode.js简单介绍
2017/08/18 Javascript
JS中精巧的自动柯里化实现方法
2017/12/12 Javascript
详解React中setState回调函数
2018/06/14 Javascript
JS中通过url动态获取图片大小的方法小结(两种方法)
2018/10/31 Javascript
微信小程序:数据存储、传值、取值详解
2019/05/07 Javascript
echarts统计x轴区间的数值实例代码详解
2019/07/07 Javascript
JavaScript解析JSON数据示例
2019/07/16 Javascript
javascript实现抢购倒计时程序
2019/08/26 Javascript
JS实现电脑虚拟键盘的操作
2020/06/24 Javascript
[40:29]2018DOTA2亚洲邀请赛 4.7总决赛 LGD vs Mineski 第一场
2018/04/10 DOTA
Python的Bottle框架中返回静态文件和JSON对象的方法
2015/04/30 Python
Python实例一个类背后发生了什么
2016/02/09 Python
python实现简单爬虫功能的示例
2016/10/24 Python
python绘制双柱形图代码实例
2017/12/14 Python
css3+伪元素实现鼠标移入时下划线向两边展开的效果
2017/04/25 HTML / CSS
MyFrenchPharma中文网:最大的法国药妆平台
2016/10/07 全球购物
全球性的奢侈品梦工厂:Forzieri(福喜利)
2019/02/20 全球购物
局域网标准
2016/09/10 面试题
幼儿园国庆节活动方案
2014/02/01 职场文书
祖国在我心中演讲稿450字
2014/09/05 职场文书
长城的导游词
2015/01/30 职场文书
话题作文之呼唤
2019/12/18 职场文书
Win11 Build 22000.829更新补丁KB5015882发布(附更新修复内容汇总)
2022/07/15 数码科技