ฉันต้องการทราบวิธีรับตำแหน่ง X และ Y ขององค์ประกอบ HTML เช่นimg
และdiv
ใน JavaScript ที่สัมพันธ์กับหน้าต่างเบราว์เซอร์
ฉันต้องการทราบวิธีรับตำแหน่ง X และ Y ขององค์ประกอบ HTML เช่นimg
และdiv
ใน JavaScript ที่สัมพันธ์กับหน้าต่างเบราว์เซอร์
คำตอบ:
วิธีการที่ถูกต้องคือการใช้element.getBoundingClientRect()
:
var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);
Internet Explorer ได้ให้การสนับสนุนนี้ตั้งแต่ตราบใดที่คุณมีแนวโน้มที่จะดูแลเกี่ยวกับและมันเป็นมาตรฐานในที่สุดCSSOM ชม เบราว์เซอร์อื่น ๆ ทั้งหมดที่นำมาใช้เป็นเวลานานแล้ว
เบราว์เซอร์บางตัวยังส่งคืนคุณสมบัติความสูงและความกว้างแม้ว่านี่จะไม่ใช่มาตรฐาน หากคุณกังวลเกี่ยวกับความเข้ากันได้ของเบราว์เซอร์รุ่นเก่าให้ตรวจสอบการแก้ไขของคำตอบนี้เพื่อการใช้งานที่ลดประสิทธิภาพ
ค่าที่ส่งคืนโดยelement.getBoundingClientRect()
สัมพันธ์กับวิวพอร์ต หากคุณต้องการมันสัมพันธ์กับองค์ประกอบอื่นเพียงแค่ลบหนึ่งสี่เหลี่ยมจากอื่น ๆ :
var bodyRect = document.body.getBoundingClientRect(),
elemRect = element.getBoundingClientRect(),
offset = elemRect.top - bodyRect.top;
alert('Element is ' + offset + ' vertical pixels from <body>');
<body>
แม้ว่า
element.getBoundingClientRect().top
ไม่ส่งกลับค่าออฟเซ็ตยอดนิยมที่ถูกต้องในกรณีของposition: fixed
องค์ประกอบใน iOS (iPhone 8) หากมีองค์ประกอบอินพุตที่มุ่งเน้นและคีย์บอร์ดเสมือนเลื่อนขึ้น ตัวอย่างเช่นหากออฟเซ็ตจริงจากด้านบนของหน้าต่างคือ 200px มันจะรายงานว่าเป็น 420px โดยที่ 220px คือความสูงของคีย์บอร์ดเสมือน หากคุณตั้งค่าองค์ประกอบposition: absolute
และวางตำแหน่งไว้ที่ตำแหน่งเดียวกับที่กำหนดไว้คุณจะได้ 200px ที่ถูกต้อง ฉันไม่รู้วิธีแก้ปัญหานี้
ไลบรารี่มีความยาวพอเหมาะเพื่อให้ได้ออฟเซ็ตที่แม่นยำสำหรับองค์ประกอบ
นี่เป็นฟังก์ชั่นง่าย ๆ ที่ทำงานในทุกสถานการณ์ที่ฉันได้ลอง
function getOffset( el ) {
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
_x += el.offsetLeft - el.scrollLeft;
_y += el.offsetTop - el.scrollTop;
el = el.offsetParent;
}
return { top: _y, left: _x };
}
var x = getOffset( document.getElementById('yourElId') ).left;
สิ่งนี้ใช้ได้สำหรับฉัน (แก้ไขจากคำตอบที่โหวตสูงสุด):
function getOffset(el) {
const rect = el.getBoundingClientRect();
return {
left: rect.left + window.scrollX,
top: rect.top + window.scrollY
};
}
ใช้สิ่งนี้เราสามารถโทร
getOffset(element).left
หรือ
getOffset(element).top
div
ที่ศูนย์กลางโดยใช้ css top:50%, left:50%; transform:translate(-50%, -50%);
... ยอดเยี่ยม เห็นด้วยเล็กน้อย @ScottBiggs คำถาม ตรรกะคือการแสวงหาความเรียบง่าย
rect
ใช้var
, หรือlet
มิฉะนั้นจะถูกกำหนดให้เป็นconst
window.rect
left: rect.left + window.scrollX + (rect.width / 2), top: rect.top + window.scrollY + (rect.height / 2)
จะกลับตำแหน่งกลางขององค์ประกอบ
หากคุณต้องการให้ทำเฉพาะใน javascript ต่อไปนี้เป็นหนึ่งใน liners ที่ ใช้getBoundingClientRect()
window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y
window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X
บรรทัดแรกจะกลับมาoffsetTop
ว่า Y ที่สัมพันธ์กับเอกสาร บรรทัดที่สองจะกลับมาoffsetLeft
บอกว่า X สัมพันธ์กับเอกสาร
getBoundingClientRect()
เป็นฟังก์ชั่นจาวาสคริปต์ที่ส่งคืนตำแหน่งขององค์ประกอบที่สัมพันธ์กับวิวพอร์ตของหน้าต่าง
องค์ประกอบ HTML ในเบราว์เซอร์ส่วนใหญ่จะมี: -
offsetLeft
offsetTop
ระบุตำแหน่งขององค์ประกอบเหล่านี้เทียบกับพาเรนต์ที่ใกล้ที่สุดที่มีโครงร่าง พาเรนต์นี้มักจะสามารถเข้าถึงได้ถ้าคุณสมบัติ offsetParent
IE และ FF3 มี
clientLeft
clientTop
คุณสมบัติเหล่านี้พบได้ทั่วไปน้อยกว่าพวกเขาระบุตำแหน่งองค์ประกอบที่มีพื้นที่ไคลเอนต์ของผู้ปกครอง (พื้นที่เบาะเป็นส่วนหนึ่งของพื้นที่ลูกค้า แต่ชายแดนและขอบไม่ได้)
หากหน้ามี - อย่างน้อย - "DIV" ใด ๆ ฟังก์ชั่นที่กำหนดโดย meouw จะโยนค่า "Y" เกินขีด จำกัด หน้าปัจจุบัน เพื่อค้นหาตำแหน่งที่แน่นอนคุณต้องจัดการทั้ง offsetParent's และ parentNode's
ลองรหัสที่ระบุด้านล่าง (มีการตรวจสอบสำหรับ FF2):
var getAbsPosition = function(el){
var el2 = el;
var curtop = 0;
var curleft = 0;
if (document.getElementById || document.all) {
do {
curleft += el.offsetLeft-el.scrollLeft;
curtop += el.offsetTop-el.scrollTop;
el = el.offsetParent;
el2 = el2.parentNode;
while (el2 != el) {
curleft -= el2.scrollLeft;
curtop -= el2.scrollTop;
el2 = el2.parentNode;
}
} while (el.offsetParent);
} else if (document.layers) {
curtop += el.y;
curleft += el.x;
}
return [curtop, curleft];
};
คุณสามารถเพิ่มคุณสมบัติสองรายการElement.prototype
เพื่อรับส่วนบน / ซ้ายขององค์ประกอบใด ๆ
Object.defineProperty( Element.prototype, 'documentOffsetTop', {
get: function () {
return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop : 0 );
}
} );
Object.defineProperty( Element.prototype, 'documentOffsetLeft', {
get: function () {
return this.offsetLeft + ( this.offsetParent ? this.offsetParent.documentOffsetLeft : 0 );
}
} );
สิ่งนี้เรียกว่า:
var x = document.getElementById( 'myDiv' ).documentOffsetLeft;
นี่คือตัวอย่างการเปรียบเทียบผลลัพธ์กับ jQuery's offset().top
และ.left
: http://jsfiddle.net/ThinkingStiff/3G7EZ/
Element.prototype
โดยทั่วไปถือว่าเป็นความคิดที่ดี มันนำไปสู่การรักษารหัสยากมาก นอกจากนี้รหัสนี้ไม่บัญชีสำหรับการเลื่อน
เพื่อดึงตำแหน่งที่สัมพันธ์กับหน้าอย่างมีประสิทธิภาพและไม่ต้องใช้ฟังก์ชันเรียกซ้ำ: (รวมถึง IE ด้วย)
var element = document.getElementById('elementId'); //replace elementId with your element's Id.
var rect = element.getBoundingClientRect();
var elementLeft,elementTop; //x and y
var scrollTop = document.documentElement.scrollTop?
document.documentElement.scrollTop:document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft?
document.documentElement.scrollLeft:document.body.scrollLeft;
elementTop = rect.top+scrollTop;
elementLeft = rect.left+scrollLeft;
วิธีการเกี่ยวกับสิ่งนี้โดยผ่าน ID ขององค์ประกอบและมันจะกลับไปทางซ้ายหรือด้านบนเรายังสามารถรวมพวกเขา:
1) ค้นหาทางซ้าย
function findLeft(element) {
var rec = document.getElementById(element).getBoundingClientRect();
return rec.left + window.scrollX;
} //call it like findLeft('#header');
2) ค้นหาด้านบน
function findTop(element) {
var rec = document.getElementById(element).getBoundingClientRect();
return rec.top + window.scrollY;
} //call it like findTop('#header');
หรือ3) ค้นหาซ้ายและบนสุดพร้อมกัน
function findTopLeft(element) {
var rec = document.getElementById(element).getBoundingClientRect();
return {top: rec.top + window.scrollY, left: rec.left + window.scrollX};
} //call it like findTopLeft('#header');
คุณอาจได้รับบริการที่ดีขึ้นโดยใช้เฟรมเวิร์ก JavaScript ที่มีฟังก์ชันเพื่อส่งคืนข้อมูลดังกล่าว (และอื่น ๆ อีกมากมาย!) ในแบบที่ไม่เกี่ยวข้องกับเบราว์เซอร์ นี่คือบางส่วน:
ด้วยเฟรมเวิร์กเหล่านี้คุณสามารถทำสิ่ง
$('id-of-img').top
ต่อไปนี้เพื่อรับพิกัด y-pixel ของภาพ
jQuery .offset ()จะได้รับพิกัดปัจจุบันขององค์ประกอบแรกหรือตั้งค่าพิกัดของทุกองค์ประกอบในชุดขององค์ประกอบที่ตรงกันสัมพันธ์กับเอกสาร
ฉันได้รับคำตอบของ @ meouw เพิ่มใน clientLeft ที่อนุญาตสำหรับเส้นขอบแล้วสร้างสามเวอร์ชัน:
getAbsoluteOffsetFromBody - คล้ายกับ @ meouw's สิ่งนี้จะได้รับตำแหน่งสัมบูรณ์ที่เกี่ยวข้องกับเนื้อหาหรือองค์ประกอบ HTML ของเอกสาร (ขึ้นอยู่กับโหมด quirks)
getAbsoluteOffsetFromGivenElement - ส่งคืนตำแหน่งสัมบูรณ์ที่สัมพันธ์กับองค์ประกอบที่กำหนด (relativeEl) โปรดทราบว่าองค์ประกอบที่กำหนดจะต้องมีองค์ประกอบ el หรือสิ่งนี้จะทำงานเช่นเดียวกับ getAbsoluteOffsetFromBody สิ่งนี้มีประโยชน์หากคุณมีสององค์ประกอบที่มีอยู่ภายในองค์ประกอบ (ที่รู้จัก) องค์ประกอบอื่น (เป็นทางเลือกหลายโหนดขึ้นไปที่ทรีโหนด) และต้องการทำให้พวกเขาอยู่ในตำแหน่งเดียวกัน
getAbsoluteOffsetFromRelative - ส่งคืนตำแหน่งสัมบูรณ์ที่สัมพันธ์กับองค์ประกอบพาเรนต์แรกที่มีตำแหน่ง: สัมพัทธ์ สิ่งนี้คล้ายกับ getAbsoluteOffsetFromGivenElement ด้วยเหตุผลเดียวกัน แต่จะไปไกลเท่าองค์ประกอบแรกที่ตรงกัน
getAbsoluteOffsetFromBody = function( el )
{ // finds the offset of el from the body or html element
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
{
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;
}
return { top: _y, left: _x };
}
getAbsoluteOffsetFromGivenElement = function( el, relativeEl )
{ // finds the offset of el from relativeEl
var _x = 0;
var _y = 0;
while( el && el != relativeEl && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
{
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;
}
return { top: _y, left: _x };
}
getAbsoluteOffsetFromRelative = function( el )
{ // finds the offset of el from the first parent with position: relative
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
{
_x += el.offsetLeft - el.scrollLeft + el.clientLeft;
_y += el.offsetTop - el.scrollTop + el.clientTop;
el = el.offsetParent;
if (el != null)
{
if (getComputedStyle !== 'undefined')
valString = getComputedStyle(el, null).getPropertyValue('position');
else
valString = el.currentStyle['position'];
if (valString === "relative")
el = null;
}
}
return { top: _y, left: _x };
}
หากคุณยังคงประสบปัญหาโดยเฉพาะอย่างยิ่งการเลื่อนคุณสามารถลองดูที่http://www.greywyvern.com/?post=331 - ฉันสังเกตเห็นอย่างน้อยหนึ่งชิ้นของรหัสที่น่าสงสัยใน getStyle ซึ่งควรเป็นเบราว์เซอร์ที่ทำงานได้ดี แต่ยังไม่ได้ทดสอบที่เหลือเลย
หากใช้ jQuery ปลั๊กอินขนาดนั้นยอดเยี่ยมและช่วยให้คุณระบุสิ่งที่คุณต้องการได้อย่างแท้จริง
เช่น
ตำแหน่งสัมพัทธ์, ตำแหน่งสัมบูรณ์, ตำแหน่งสัมบูรณ์โดยไม่ต้องแพ็ดด ...
มันบอกต่อไปว่ามีหลายอย่างที่คุณสามารถทำได้
นอกจากนี้โบนัสของการใช้ jQuery ก็คือขนาดไฟล์ที่เบาและใช้งานง่ายคุณจะไม่กลับไปที่ JavaScript หลังจากนั้น
นี่คือรหัสที่ดีที่สุดที่ฉันสามารถสร้างได้ (ทำงานใน iframe เช่นกันซึ่งแตกต่างจาก jQuery's offset ()) ดูเหมือนว่า webkit มีพฤติกรรมที่แตกต่างกันเล็กน้อย
ตามความคิดเห็นของ meouw:
function getOffset( el ) {
var _x = 0;
var _y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
_x += el.offsetLeft - el.scrollLeft;
_y += el.offsetTop - el.scrollTop;
// chrome/safari
if ($.browser.webkit) {
el = el.parentNode;
} else {
// firefox/IE
el = el.offsetParent;
}
}
return { top: _y, left: _x };
}
หากคุณใช้ jQuery นี่อาจเป็นวิธีง่ายๆ:
<script>
var el = $("#element");
var position = el.position();
console.log( "left: " + position.left + ", top: " + position.top );
</script>
ความแตกต่างระหว่างเล็กและน้อย
function getPosition( el ) {
var x = 0;
var y = 0;
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
x += el.offsetLeft - el.scrollLeft;
y += el.offsetTop - el.scrollTop;
el = el.offsetParent;
}
return { top: y, left: x };
}
ดูตัวอย่างพิกัด: http://javascript.info/tutorial/coordinates
<svg>
องค์ประกอบเช่นไม่ได้offsetLeft
, offsetTop
และoffsetParent
คุณสมบัติ
DIV
หรือไม่IMG
SVG
ดู "ดูพิกัดตัวอย่าง" หรือไม่ คุณสามารถค้นหาวัตถุ svg คือการเรียกใช้ตำแหน่งgetOffsetRectลองและทำงานของวัตถุ
วิธีที่สะอาดที่ฉันได้พบเป็นรุ่นที่เรียบง่ายของเทคนิคที่ใช้โดยของ offset
jQuery คล้ายกับบางส่วนของคำตอบอื่น ๆ จะเริ่มต้นด้วยgetBoundingClientRect
; จากนั้นใช้window
และdocumentElement
เพื่อปรับสำหรับตำแหน่งการเลื่อนตลอดจนสิ่งต่าง ๆ เช่นระยะขอบบนbody
(มักเป็นค่าเริ่มต้น)
var rect = el.getBoundingClientRect();
var docEl = document.documentElement;
var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;
ในขณะนี้มีแนวโน้มที่จะหายไปที่ด้านล่างของคำตอบมากมายโซลูชั่นชั้นนำที่นี่ไม่ทำงานสำหรับฉัน
เท่าที่ฉันจะบอกได้ว่าไม่มีคำตอบอื่นใดช่วย
สถานการณ์ :
ในหน้า HTML5 ฉันมีเมนูที่เป็นองค์ประกอบ nav ภายในส่วนหัว (ไม่ใช่ส่วนหัว แต่เป็นส่วนหัวในองค์ประกอบอื่น)
ฉันต้องการให้การนำทางติดไปด้านบนเมื่อผู้ใช้เลื่อนไปที่หน้า แต่ก่อนหน้านี้ส่วนหัวอยู่ในตำแหน่งที่แน่นอน (ดังนั้นฉันจึงสามารถวางทับสิ่งอื่นเล็กน้อย)
วิธีการแก้ปัญหาข้างต้นไม่เคยทำให้เกิดการเปลี่ยนแปลงเพราะ. offsetTop จะไม่เปลี่ยนแปลงเนื่องจากเป็นองค์ประกอบตำแหน่งที่แน่นอน นอกจากนี้คุณสมบัติ. scrollTop เป็นเพียงส่วนบนสุดขององค์ประกอบส่วนใหญ่ ... นั่นคือจะบอกว่า 0 และจะเป็น 0 เสมอ
การทดสอบใด ๆ ที่ฉันทำโดยใช้สองสิ่งนี้ (และเหมือนกันกับผลลัพธ์ของ getBoundingClientRect) จะไม่บอกฉันว่าแถบด้านบนสุดของแถบการนำทางที่เคยเลื่อนไปด้านบนของหน้าสามารถดูได้ (อีกครั้งตามที่รายงานในคอนโซล เกิดขึ้น)
วิธีการแก้ปัญหา
การแก้ปัญหาสำหรับผมที่ได้รับใช้
window.visualViewport.pageTop
ค่าของคุณสมบัติ pageTop สะท้อนถึงส่วนที่สามารถดูได้ของหน้าจอดังนั้นให้ฉันติดตามตำแหน่งที่องค์ประกอบอ้างอิงถึงขอบเขตของพื้นที่ที่สามารถดูได้
อาจไม่จำเป็นต้องพูดทุกครั้งที่ฉันต้องทำการเลื่อนฉันคาดว่าจะใช้โซลูชันนี้เพื่อตอบสนองการเคลื่อนไหวขององค์ประกอบที่ถูกเลื่อนโดยทางโปรแกรม
หวังว่ามันจะช่วยคนอื่น
หมายเหตุสำคัญ: สิ่งนี้ดูเหมือนว่าจะใช้งานได้ใน Chrome และ Opera ในขณะนี้ & ไม่ใช่ใน Firefox (6-2018) ... จนกระทั่ง Firefox รองรับ visualViewport ฉันไม่แนะนำให้ใช้วิธีนี้ (และฉันหวังว่าพวกเขาจะทำเร็ว ๆ นี้ ... มีความรู้สึกมากกว่าส่วนที่เหลือ)
อัปเดต:
โปรดทราบเกี่ยวกับโซลูชันนี้
ในขณะที่ฉันยังพบสิ่งที่ฉันค้นพบว่ามีค่ามากสำหรับสถานการณ์ที่ "... ตอบสนองโดยทางโปรแกรมต่อการเคลื่อนไหวขององค์ประกอบที่ถูกเลื่อน" ใช้ได้ ทางออกที่ดีกว่าสำหรับปัญหาที่ฉันมีคือการใช้ CSS เพื่อกำหนดตำแหน่ง: เหนียวในองค์ประกอบ ใช้เหนียวคุณสามารถมีความโดดองค์ประกอบที่ด้านบนโดยไม่ต้องใช้ JavaScript (หมายเหตุ: มีครั้งนี้จะไม่ทำงานอย่างมีประสิทธิภาพเป็นที่เปลี่ยนแปลงองค์ประกอบคงที่ แต่สำหรับการใช้งานมากที่สุดวิธีเหนียวมีแนวโน้มที่จะดีกว่า)
UPDATE01:
ดังนั้นผมจึงตระหนักว่า สำหรับหน้าอื่นฉันมีข้อกำหนดที่ฉันต้องการตรวจสอบตำแหน่งขององค์ประกอบในการตั้งค่าการเลื่อนที่ซับซ้อนอย่างอ่อนโยน (parallax plus องค์ประกอบที่เลื่อนผ่านมาเป็นส่วนหนึ่งของข้อความ) ฉันตระหนักในสถานการณ์ที่ว่าสิ่งต่อไปนี้ให้คุณค่าที่ฉันใช้เพื่อพิจารณาว่าจะทำอะไรเมื่อไหร่:
let bodyElement = document.getElementsByTagName('body')[0];
let elementToTrack = bodyElement.querySelector('.trackme');
trackedObjPos = elementToTrack.getBoundingClientRect().top;
if(trackedObjPos > 264)
{
bodyElement.style.cssText = '';
}
หวังว่าคำตอบนี้มีประโยชน์มากขึ้นในขณะนี้
ฉันทำแบบนี้ดังนั้นจึงสามารถใช้งานร่วมกับเบราว์เซอร์รุ่นเก่าได้
// For really old browser's or incompatible ones
function getOffsetSum(elem) {
var top = 0,
left = 0,
bottom = 0,
right = 0
var width = elem.offsetWidth;
var height = elem.offsetHeight;
while (elem) {
top += elem.offsetTop;
left += elem.offsetLeft;
elem = elem.offsetParent;
}
right = left + width;
bottom = top + height;
return {
top: top,
left: left,
bottom: bottom,
right: right,
}
}
function getOffsetRect(elem) {
var box = elem.getBoundingClientRect();
var body = document.body;
var docElem = document.documentElement;
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
var clientTop = docElem.clientTop;
var clientLeft = docElem.clientLeft;
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
var bottom = top + (box.bottom - box.top);
var right = left + (box.right - box.left);
return {
top: Math.round(top),
left: Math.round(left),
bottom: Math.round(bottom),
right: Math.round(right),
}
}
function getOffset(elem) {
if (elem) {
if (elem.getBoundingClientRect) {
return getOffsetRect(elem);
} else { // old browser
return getOffsetSum(elem);
}
} else
return null;
}
ข้อมูลเพิ่มเติมเกี่ยวกับพิกัดใน JavaScript ที่นี่: http://javascript.info/tutorial/coordinates
ในการรับออฟเซ็ตรวมขององค์ประกอบคุณสามารถสรุปการหักล้างพาเรนต์ทั้งหมดซ้ำ:
function getParentOffsets(el): number {
if (el.offsetParent) {
return el.offsetParent.offsetTop + getParentOffset(el.offsetParent);
} else {
return 0;
}
}
ด้วยฟังก์ชั่นยูทิลิตี้นี้การชดเชยยอดรวมทั้งหมดขององค์ประกอบ dom คือ:
el.offsetTop + getParentOffsets(el);
/**
*
* @param {HTMLElement} el
* @return {{top: number, left: number}}
*/
function getDocumentOffsetPosition(el) {
var position = {
top: el.offsetTop,
left: el.offsetLeft
};
if (el.offsetParent) {
var parentPosition = getDocumentOffsetPosition(el.offsetParent);
position.top += parentPosition.top;
position.left += parentPosition.left;
}
return position;
}
ขอบคุณThinkingStiffสำหรับคำตอบนี่เป็นอีกเวอร์ชั่นเท่านั้น
ฉันใช้โซลูชันของ Andy E เพื่อวาง bootstrap 2 modal ขึ้นอยู่กับลิงค์ในแถวตารางที่ผู้ใช้คลิก หน้านี้เป็นหน้า Tapestry 5 และจาวาสคริปต์ด้านล่างจะถูกนำเข้าในคลาสหน้าจาวา
javascript:
function setLinkPosition(clientId){
var bodyRect = document.body.getBoundingClientRect(),
elemRect = clientId.getBoundingClientRect(),
offset = elemRect.top - bodyRect.top;
offset = offset + 20;
$('#serviceLineModal').css("top", offset);
}
รหัสกิริยาของฉัน:
<div id="serviceLineModal" class="modal hide fade add-absolute-position" data-backdrop="static"
tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="top:50%;">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
<h3 id="myModalLabel">Modal header</h3>
</div>
<div class="modal-body">
<t:zone t:id="modalZone" id="modalZone">
<p>You selected service line number: ${serviceLineNumberSelected}</p>
</t:zone>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<!-- <button class="btn btn-primary">Save changes</button> -->
</div>
ลิงค์ในลูป:
<t:loop source="servicesToDisplay" value="service" encoder="encoder">
<tr style="border-right: 1px solid black;">
<td style="white-space:nowrap;" class="add-padding-left-and-right no-border">
<a t:type="eventLink" t:event="serviceLineNumberSelected" t:context="service.serviceLineNumber"
t:zone="pageZone" t:clientId="modalLink${service.serviceLineNumber}"
onmouseover="setLinkPosition(this);">
<i class="icon-chevron-down"></i> <!-- ${service.serviceLineNumber} -->
</a>
</td>
และรหัส java ในระดับหน้า:
void onServiceLineNumberSelected(String number){
checkForNullSession();
serviceLineNumberSelected = number;
addOpenServiceLineDialogCommand();
ajaxResponseRenderer.addRender(modalZone);
}
protected void addOpenServiceLineDialogCommand() {
ajaxResponseRenderer.addCallback(new JavaScriptCallback() {
@Override
public void run(JavaScriptSupport javascriptSupport) {
javascriptSupport.addScript("$('#serviceLineModal').modal('show');");
}
});
}
หวังว่านี่จะช่วยใครซักคนโพสต์นี้ช่วยได้
หลังจากการวิจัยและทดสอบมากมายดูเหมือนว่าจะได้ผล
function getPosition(e) {
var isNotFirefox = (navigator.userAgent.toLowerCase().indexOf('firefox') == -1);
var x = 0, y = 0;
while (e) {
x += e.offsetLeft - e.scrollLeft + (isNotFirefox ? e.clientLeft : 0);
y += e.offsetTop - e.scrollTop + (isNotFirefox ? e.clientTop : 0);
e = e.offsetParent;
}
return { x: x + window.scrollX, y: y + window.scrollY };
}
แค่คิดว่าฉันจะโยนมันออกไปที่นั่นเช่นกัน
ฉันไม่สามารถทดสอบได้ในเบราว์เซอร์รุ่นเก่า แต่ใช้งานได้กับ 3 อันดับสูงสุดล่าสุด :)
Element.prototype.getOffsetTop = function() {
return ( this.parentElement )? this.offsetTop + this.parentElement.getOffsetTop(): this.offsetTop;
};
Element.prototype.getOffsetLeft = function() {
return ( this.parentElement )? this.offsetLeft + this.parentElement.getOffsetLeft(): this.offsetLeft;
};
Element.prototype.getOffset = function() {
return {'left':this.getOffsetLeft(),'top':this.getOffsetTop()};
};
เนื่องจากเบราว์เซอร์ที่แตกต่างกันมีการแสดงเส้นขอบการเว้นระยะขอบและอื่น ๆ ในวิธีที่ต่าง ฉันเขียนฟังก์ชันเล็กน้อยเพื่อดึงตำแหน่งด้านบนและด้านซ้ายขององค์ประกอบเฉพาะในทุกองค์ประกอบรากที่คุณต้องการในมิติที่แม่นยำ:
function getTop(root, offset) {
var rootRect = root.getBoundingClientRect();
var offsetRect = offset.getBoundingClientRect();
return offsetRect.top - rootRect.top;
}
เพื่อดึงตำแหน่งที่เหลือคุณต้องกลับมา:
return offsetRect.left - rootRect.left;
รับตำแหน่ง div ในส่วนซ้ายและบน
var elm = $('#div_id'); //get the div
var posY_top = elm.offset().top; //get the position from top
var posX_left = elm.offset().left; //get the position from left
el.offsetTop
และel.offsetLeft
(OP ไม่ได้พูดอะไรเกี่ยวกับ jQuery ... ฉันไม่แน่ใจว่าทำไมคำตอบของคุณใช้ jQuery ทั้ง ... )