一、offset()

作用:
返回被选元素相对于文档(document)的偏移坐标

二、三种情况使用:

1、$().offset()

<body><script src="jQuery.js"></script><p id="pTwo">这是divTwo</p><script>  $("#pTwo").offset() //{top: 16, left: 8}</script></body>复制代码

源码:

   //返回目标元素相对于doucument的偏移坐标,    //即距离浏览器左上角的距离

    // 返回偏移坐标:$(selector).offset()    // 设置偏移坐标:$(selector).offset({top:value,left:value})    // 使用函数设置偏移坐标:$(selector).offset(function(index,currentoffset))    // offset() relates an element's border box to the document origin    //源码10500行    //options即参数    //arguments是参数对象    offset: function( options ) {      // Preserve chaining for setter      //如果是有参数的,参数是undefined则返回目标元素本身,      //否则为每个目标元素设置options      console.log(options,arguments,'arguments10476')      //$().offset()不走这里      if ( arguments.length ) {        console.log('aaa','vvv10507')        return options === undefined ?          this :          this.each( function( i ) {            //为每个目标元素设置options            jQuery.offset.setOffset( this, options, i );          } );      }

      var rect, win,        //获取DOM节点        elem = this[ 0 ];

      if ( !elem ) {        return;      }

      // jQuery不支持获取隐藏元素的偏移坐标。      // 同理,也无法取得隐藏元素的 border, margin, 或 padding 信息      //所以如果元素是隐藏的,默认返回0值      // Return zeros for disconnected and hidden (display: none) elements (gh-2310)      // Support: IE <=11 only      // Running getBoundingClientRect on a      // disconnected node in IE throws an error      //对IE的特殊处理      if ( !elem.getClientRects().length ) {        return { top: 0, left: 0 };      }

      // Get document-relative position by adding viewport scroll to viewport-relative gBCR      //返回元素的大小及其相对于视口的位置      //https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect      rect = elem.getBoundingClientRect();      //返回所属文档的默认窗口对象(只读)      //原点坐标      win = elem.ownerDocument.defaultView;      //pageXOffset,pageYOffset 相当于 scrollX 和 scrollY       //返回文档在窗口左上角水平 x 和垂直 y 方向滚动的像素      return {        //16    0        //        top: rect.top + win.pageYOffset,        //8     0        left: rect.left + win.pageXOffset      };    },复制代码

解析:
由于$().offset()没有参数,所以源码里的两个 if 可以忽略,所以offset()的本质即:

  let p = document.getElementById("pTwo");  let rect=p.getBoundingClientRect()  //返回所属文档的默认窗口对象(只读)  //原点坐标  let win = p.ownerDocument.defaultView;  let offsetObj={    top: rect.top + win.pageYOffset,    left: rect.left + win.pageXOffset  }  console.log(offsetObj,'win18')复制代码

(1)getBoundingClientRect()
该方法用于获取某个元素相对于视窗的位置集合,并返回一个对象,该对象中有top, right, bottom, left等属性,简单点就是相对于原坐标(默认是左上角)的偏移量

(2)window.pageXOffset、window.pageYOffset
返回文档在窗口左上角水平 x 和垂直 y 方向滚动的像素,相当于 scrollX 和 scrollY,简单点就是滚动的偏移量

所以offset()本质即:
相对于原坐标的偏移量+滚动的偏移量的总和。

2、$().offset({top:15,left:15})

$("#pTwo").offset({top:15,left:15})复制代码

源码:
当有参数的时候,就会走 if 中,通过jQuery.offset.setOffset( )来处理:

 if ( arguments.length ) {        return options === undefined ?          this :          this.each( function( i ) {            //为每个目标元素设置options            jQuery.offset.setOffset( this, options, i );          } );      }复制代码
  • jQuery.offset.setOffset( )
  //offset()的关键方法  //源码10403行  jQuery.offset = {    setOffset: function( elem, options, i ) {      var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,        //获取元素的position属性的值        //static        position = jQuery.css( elem, "position" ),        //过滤成标准jQuery对象        curElem = jQuery( elem ),        props = {};

      // Set position first, in-case top/left are set even on static elem      //指定相对定位relative      if ( position === "static" ) {        elem.style.position = "relative";      }      //{left:8,top:16}      curOffset = curElem.offset();      //0px      curCSSTop = jQuery.css( elem, "top" );      //0px      curCSSLeft = jQuery.css( elem, "left" );      // 如果定位position是(绝对定位absolute或固定定位fixed),      // 并且top,left属性包含auto的话      //false      calculatePosition = ( position === "absolute" || position === "fixed" ) &&        ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;      // Need to be able to calculate position if either      // top or left is auto and position is either absolute or fixed      if ( calculatePosition ) {        curPosition = curElem.position();        curTop = curPosition.top;        curLeft = curPosition.left;

      } else {        //0 0        curTop = parseFloat( curCSSTop ) || 0;        curLeft = parseFloat( curCSSLeft ) || 0;      }      //如果传的参数是function{}的话      if ( isFunction( options ) ) {

        // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)        options = options.call( elem, i, jQuery.extend( {}, curOffset ) );      }      //如果传的参数的有top值      if ( options.top != null ) {        //参数 top - offset().top + element.top        props.top = ( options.top - curOffset.top ) + curTop;      }      //如果传的参数的有left值      if ( options.left != null ) {        //参数 left - offset().left + element.left        props.left = ( options.left - curOffset.left ) + curLeft;      }      //自己没见过使用 using 的情况。。      if ( "using" in options ) {        options.using.call( elem, props );

      }      //所以一般走这里,为当前元素设置top,left属性      else {        //position:relative        //top:xxx        //left:xxx        curElem.css( props );      }    }  };复制代码

解析:
(1)先判断当前元素的 position 的值,没有设置 position 属性的话,默认为 relative,并获取元素的 top、left 属性的值
(2)返回一个对象 obj,obj 的 top 是参数的 top - 默认偏移(offset)的 top + position 设置的 top(没有设置,默认为0),obj 的 left 同理。

也就是说 offset({top:15,;eft:15}) 的本质为:
参数的属性减去对应的默认offset属性加上position上的对应属性。

//伪代码offset().top = elem. getBoundingClientRect().top + document. pageYOffset

top: offset({top:15}).top - offset().top + position.top也就是:offset({top:15}).top - (elem. getBoundingClientRect().top + document. pageYOffset) + position.top复制代码

3、$().offset(function(){})

  $("#pTwo").offset(function(index,currentoffset){    let newPos={};    newPos.left=currentoffset.left+15;    newPos.top=currentoffset.top+15;    return newPos;  });复制代码

源码:

//如果传的参数是function{}的话      if ( isFunction( options ) ) {        // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)        options = options.call( elem, i, jQuery.extend( {}, curOffset ) );      }复制代码

解析:
让当前元素通过call 去调用参数中的 function(){} 方法,call 的参数必须一个一个放进去,上面源码中,call 参数有 i、jQuery.extend( {}, curOffset )

  • jQuery.extend( {}, curOffset )
    暂不解析jQuery.extend(),但这里的作用 不用看源码,也知道是将 element.offset() 的属性赋值给新建的空对象 {} 。

所以 $().offset(function(){}) 的本质即:相对于 element.offset() ,对其 top,left进行操作,而不是像 offset({top:xxx,left:xxx}) 那样相对于左上角原点进行操作(这样就需要先减去offset()中的top、left的值了)。

本文结束,五一愉快~


(完)

jQuery源码解析之offset()相关推荐

  1. jquery源码解析:代码结构分析

    本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94)     定义了一些变量和函数,   jQuery = function() ...

  2. JQuery 源码解析资料

    2019独角兽企业重金招聘Python工程师标准>>> jQuery源码分析系列目录 jQuery源码解读-理解架构 jQuery源码解析(架构与依赖模块) jQuery v1.10 ...

  3. jQuery源码解析(架构与依赖模块)

    jQuery设计理念 引用百科的介绍: jQuery是继prototype之后又一个优秀的Javascript框架.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1. ...

  4. jQuery源码解析(架构与依赖模块)第一章 理解架构

    1-1 jQuery设计理念 引用百科的介绍: jQuery是继prototype之后又一个优秀的Javascript框架.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, F ...

  5. jquery源码解析:jQuery数据缓存机制详解2

    上一课主要讲了jQuery中的缓存机制Data构造方法的源码解析,这一课主要讲jQuery是如何利用Data对象实现有关缓存机制的静态方法和实例方法的.我们接下来,来看这几个静态方法和实例方法的源码解 ...

  6. jQuery 源码解析一:jQuery 类库整体架构设计解析

    如果是做 web 的话,相信都要对 Dom 进行增删查改,那大家都或多或少接触到过 jQuery 类库,其最大特色就是强大的选择器,让开发者脱离原生 JS 一大堆 getElementById.get ...

  7. jQuery源码解析之on事件绑定

    本文采用的jQuery源码为jquery-3.2.1.js jquery的on方法用来在选定的元素上绑定一个或多个事件处理函数. 当参数selector存在时,通常会用来对已经存在的元素或将来即将添加 ...

  8. 浅谈jquery源码解析

    本文主要是针对jquery  v3.x版本来描述的,将从以下几个方面谈谈我对jquery的认识, 总体架构 $与$.fn jQuery.fn.init  (重要) jQuery.extend  与jQ ...

  9. jQuery源码解析之position()

    position() 作用: 返回被选元素相对于父元素(parent)的偏移坐标 使用: 直接调用$().position()即可,该方法没有 arguments(参数对象) <body> ...

最新文章

  1. Xmas is coming....
  2. caffe学习笔记25-过拟合原因及分析
  3. 利用事件进行窗体间传值
  4. 关于HTTPS的七个误解
  5. 使用 stm32实现锂电充电_千次循环使用,ZMI可充电锂电池套装,够用一辈子吗?...
  6. mybatis初始化mysql_SimpleMybatisMysql
  7. paip.c++ qt 外部dll共享库的导入以及引用
  8. Unity音频可视化插件
  9. Apache Ant安装与配置
  10. “AI四小龙”神话破灭?依图终止IPO,云从大裁员,旷视巨亏不止
  11. C盘清理——借助软件TreeSizeFree【网盘分享】(亲测有效)
  12. FPGA两片RAM的乒乓操作
  13. Mysql安装后环境变量配置
  14. linux开启PREEMPT_RT
  15. 【Go】解析X509
  16. Java-dao模式
  17. led照明灯哪个牌子的比较好?质量超好的LED护眼台灯推荐
  18. HDU6194 后缀数组
  19. Wow魔兽世界服务器搭建详细教程,魔兽世界服务器配置要求
  20. iphone 使用自定义字体

热门文章

  1. 深刻理解 React (一) ——JSX和虚拟DOM
  2. Git学习笔记总结和注意事项
  3. 【iOS系列】-iOS中内存管理
  4. PyQt4设置窗口左上角的小图标
  5. 这个我过滤概述UIPickerView键盘处理
  6. iOS Crash文件的解析(一)
  7. asp,net 读写cookie(个人笔记)
  8. C#中i=i++值不变的一个解释
  9. java抛出异常thorw和throws的用法
  10. 未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序 解决方案