摘要:注意的本質是的解析整體上看,是一個語句由于的元素,是相對于瀏覽器窗口進行定位的,所以它的偏移就是,即獲取某個元素相對于視窗的位置。注意的本質是的完
position()
作用:
返回被選元素相對于父元素(parent)的偏移坐標
使用:
直接調用$().position()即可,該方法沒有 arguments(參數對象)
這是divTwo
源碼:
// 返回被選元素相對于父元素(parent)的偏移坐標 // 可以理解成被選元素設置為absolute, // 然后設置left、top的值就是相對于父元素的偏移坐標 // 源碼10571行 // position() relates an element"s margin box to its offset parent"s padding box // This corresponds to the behavior of CSS absolute positioning position: function() { // 如果DOM元素不存在,直接返回 if ( !this[ 0 ] ) { return; } var offsetParent, offset, doc, elem = this[ 0 ], parentOffset = { top: 0, left: 0 }; // position:fixed elements are offset from the viewport, which itself always has zero offset // position:fixed的元素,是相對于瀏覽器窗口進行定位的, // 所以它的偏移就是getBoundingClientRect(),即獲取某個元素相對于視窗的位置 if ( jQuery.css( elem, "position" ) === "fixed" ) { // Assume position:fixed implies availability of getBoundingClientRect offset = elem.getBoundingClientRect(); } // 除去position是fixed的情況 else { // 獲取被選元素相對于文檔(document)的偏移坐標 offset = this.offset(); // Account for the *real* offset parent, which can be the document or its root element // when a statically positioned element is identified doc = elem.ownerDocument; //定位目標元素的父元素(position不為static的元素) offsetParent = elem.offsetParent || doc.documentElement; // 如果父元素是/的話,將父元素重新定位為它們的父元素 // body的父元素是html,html的父元素是document while ( offsetParent && ( offsetParent === doc.body || offsetParent === doc.documentElement ) && jQuery.css( offsetParent, "position" ) === "static" ) { offsetParent = offsetParent.parentNode; } // 如果定位父元素存在,并且不等于目標元素,并且定位元素類型是 "元素類型" if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) { // Incorporate borders into its offset, since they are outside its content origin parentOffset = jQuery( offsetParent ).offset(); // 這兩行代碼的意思是父元素的offset()要從padding算起,不包括border // 所以需要去掉border // jQuery.css( element, "borderTopWidth", true )的 true 表示返回數字,而不帶單位 px parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true ); parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true ); } } // Subtract parent offsets and element margins // 可以看出,$().position()的本質是目標元素的offset()減去父元素的offset(),同時還要算上目標元素的margin,因為盒子模型(關鍵)。 //(注意:offset()的本質是getBoundingClientRect()的top、left + pageYOffset、pageXOffset) return { top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) }; },
解析:
整體上看,是一個 if(...fixed) { } esle { } 語句
(1)if ( jQuery.css( elem, "position" ) === "fixed" )
if ( jQuery.css( elem, "position" ) === "fixed" ) { // Assume position:fixed implies availability of getBoundingClientRect offset = elem.getBoundingClientRect(); } return { top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) };
由于position:fixed的元素,是相對于瀏覽器窗口進行定位的,所以它的偏移就是getBoundingClientRect(),即獲取某個元素相對于視窗的位置。
注意:
① getBoundingClientRect() 計算的是目標元素的border的位置(左上角),是不包括margin的
② 如果不加上margin的話(代碼是通過減去,來算上margin的),是不準確的,看下圖
所以源碼最后會:
- jQuery.css( elem, "marginTop", true ) - jQuery.css( elem, "marginLeft", true )
(2)jQuery.css( elem, "width", true )
true的作用是返回該屬性的數字,而不帶單位 px
(3)定位父元素存在,并且不等于目標元素,并且定位元素類型是 "元素類型"的話
if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 )
是要減去border屬性的值的
parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true ); parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
為啥?舉個例子:
let p=document.querySelector("#pTwo") console.log(p.getBoundingClientRect(),"pTwo11"); //x:8,y:16
設置 borderLeftWidth 為 8 像素
let p=document.querySelector("#pTwo") p.style.borderLeftWidth="8px" console.log(p.getBoundingClientRect(),"pTwo11"); //x:8,y:16
可以看到getBoundingClientRect()指定坐標是到border上的,這是不準確的,因為在里面的子元素的位置也會受父元素的border影響,所以父元素的坐標需要越過border
綜上:
可以看出,$().position()的本質是目標元素的 offset() 減去父元素的 offset(),同時還要算上目標元素的 margin,算上父元素的border。
(注意:offset()的本質是getBoundingClientRect()的top、left + pageYOffset、pageXOffset)
Github:
https://github.com/AttackXiao...
(完)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104106.html
摘要:也就是說的本質為參數的屬性減去對應的默認屬性加上上的對應屬性。所以的本質即相對于,對其,進行操作,而不是像那樣相對于左上角原點進行操作這樣就需要先減去中的的值了。 showImg(https://upload-images.jianshu.io/upload_images/5518628-d5ec366642ca36ab.jpg?imageMogr2/auto-orient/strip...
摘要:前言需要先看源碼解析之和一舉例的寬度先變成,再變成,最后變成這是在異步調用中,進行同步調用動畫是異步的就是連續調用二作用通過樣式將元素從一個狀態改變為另一個狀態源碼之前有說過是的方法源碼行是否是空對象,方法執行單個動畫的封裝的本質是執行 showImg(https://segmentfault.com/img/remote/1460000019594521); 前言:需要先看 jQue...
摘要:五作用的關鍵方法,用來從目標節點克隆數據添加事件給克隆的元素注意采用數據分離的方法來保存上的事件和數據,利用標記每個元素,然后在內存上,將每個元素相關的數據放到內存中,然后在和內存的數據之間建立映射。 showImg(https://segmentfault.com/img/remote/1460000018991125); 前言:這篇講完后,jQuery的文檔處理就告一段落了,有空我...
摘要:一起源方法最終是用綁定事件的而方法正是等于二作用觸發綁定的事件的處理程序源碼源碼行即原生觸發事件的處理程序修正對象獲取事件的處理程序集合,結構如下從數據緩存中獲取事件處理集合即目標元素委托目標這段代碼壓根不會執行,因為全局搜索沒找到結構 showImg(https://segmentfault.com/img/remote/1460000019464031); 一、起源jQuery.e...
閱讀 3190·2021-11-10 11:35
閱讀 1295·2019-08-30 13:20
閱讀 1117·2019-08-29 16:18
閱讀 2131·2019-08-26 13:54
閱讀 2155·2019-08-26 13:50
閱讀 955·2019-08-26 13:39
閱讀 2473·2019-08-26 12:08
閱讀 1951·2019-08-26 10:37