การค้นหาตำแหน่งขององค์ประกอบที่สัมพันธ์กับเอกสาร


113

วิธีใดง่ายที่สุดในการกำหนดตำแหน่งองค์ประกอบที่สัมพันธ์กับหน้าต่างเอกสาร / เนื้อหา / เบราว์เซอร์

ตอนนี้ฉันกำลังใช้อยู่.offsetLeft/offsetTopแต่วิธีนี้ให้ตำแหน่งที่สัมพันธ์กับองค์ประกอบหลักเท่านั้นดังนั้นคุณต้องกำหนดจำนวนผู้ปกครองกับองค์ประกอบของร่างกายเพื่อให้ทราบตำแหน่งที่สัมพันธ์กับตำแหน่งของเนื้อหา / หน้าต่างเบราว์เซอร์ / เอกสาร

วิธีนี้ยังยุ่งยาก

คำตอบ:


59

คุณสามารถสำรวจoffsetParentขึ้นไปที่ระดับบนสุดของ DOM

function getOffsetLeft( elem )
{
    var offsetLeft = 0;
    do {
      if ( !isNaN( elem.offsetLeft ) )
      {
          offsetLeft += elem.offsetLeft;
      }
    } while( elem = elem.offsetParent );
    return offsetLeft;
}

28
ไม่เป็นเช่นนั้นเมื่อผู้ปกครอง (โดยเฉพาะองค์ประกอบ html !!!) มีระยะขอบพายหรือเส้นขอบ
Flash Thunder

เกี่ยวกับสิ่งที่มาร์จิ้น ... มันอาจช่วยในการตั้งค่าขนาดกล่องเป็น border-box ... หรือบางอย่างตามบรรทัดเหล่านั้น ... ไม่มีอะไรที่แก้ไขไม่ได้ ...

ขั้นแรกคุณต้องตัดสินใจว่าจะคำนึงถึงเส้นขอบและระยะขอบตามขนาดกล่องหรือไม่ ประการที่สองควรพิจารณาระยะขอบที่ยุบ และสุดท้ายจะมีสถานการณ์ที่ซับซ้อนมากขึ้นในอนาคตซึ่งจะทำให้คำตอบนี้แย่ลง
xianshenglu

6
เหตุใดจึงเป็นคำตอบที่ได้รับการยอมรับ สิ่งนี้ล้าสมัยและมีประสิทธิภาพต่ำ ให้ความช่วยเหลือตัวเองและใช้ getBoundingClientRect () ตามที่แนะนำในคำตอบอื่น ๆ
Fabian von Ellerts

177

คุณสามารถขึ้นด้านบนและด้านซ้ายโดยไม่ต้องข้าม DOM เช่นนี้:

function getCoords(elem) { // crossbrowser version
    var box = elem.getBoundingClientRect();

    var body = document.body;
    var docEl = document.documentElement;

    var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
    var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;

    var clientTop = docEl.clientTop || body.clientTop || 0;
    var clientLeft = docEl.clientLeft || body.clientLeft || 0;

    var top  = box.top +  scrollTop - clientTop;
    var left = box.left + scrollLeft - clientLeft;

    return { top: Math.round(top), left: Math.round(left) };
}

6
คำตอบนี้ไม่ได้คำนึงถึงการชดเชยของผู้ปกครอง มันสัมพันธ์กับวิวพอร์ตเท่านั้น
Nickey

3
@Nickey ไม่เป็นความจริง - ตำแหน่งวิวพอร์ตบวกกับการตรวจสอบออฟเซ็ตการเลื่อนจะให้พิกัดที่สัมพันธ์กับเอกสารทั้งหมด
natchiketa

1
สามารถบั๊กกี้บนอุปกรณ์มือถือได้stackoverflow.com/a/32623832/962634ต้องการค้นคว้า
โหระพา

1
ทำไมคุณถึงลบ clientTop / clientLeft?
Teemoh

1
@Teemoh clientTop / clientLeft สอดคล้องกับค่าเส้นขอบบน<html>องค์ประกอบ
Raphael Rafatpanah

99

คุณสามารถใช้element.getBoundingClientRect()เพื่อดึงข้อมูลตำแหน่งองค์ประกอบที่สัมพันธ์กับวิวพอร์ต

จากนั้นใช้document.documentElement.scrollTopในการคำนวณออฟเซ็ตวิวพอร์ต

ผลรวมของทั้งสองจะให้ตำแหน่งองค์ประกอบที่สัมพันธ์กับเอกสาร:

element.getBoundingClientRect().top + document.documentElement.scrollTop

10
สัมพันธ์กับวิวพอร์ตไม่เหมือนกับเมื่อเทียบกับเอกสาร หากเลื่อนหน้าลงมาเล็กน้อยส่วนบนที่สัมพันธ์กับวิวพอร์ตจะเป็นตัวเลขที่น้อยกว่าด้านบนที่สัมพันธ์กับเอกสาร
MrVimes

14
เขาเริ่มสัมพันธ์กับวิวพอร์ตและเพิ่ม scrollY เพื่อให้สัมพันธ์กับเอกสาร
Joaquin Cuenca Abela

2
document.documentElement.scrollTopใช้ไม่ได้ใน Safari ให้ใช้window.scrollYแทน
Fabian von Ellerts

7

ฉันขอแนะนำให้ใช้

element.getBoundingClientRect()

ตามที่เสนอที่นี่ แทนการคำนวณชดเชยด้วยตนเองผ่านoffsetLeft , offsetTopและoffsetParent ตามที่เสนอไว้ที่นี่ใน บางสถานการณ์ * การส่งผ่านด้วยตนเองให้ผลลัพธ์ที่ไม่ถูกต้อง ดู Plunker นี้: http://plnkr.co/pC8Kgj

* เมื่อองค์ประกอบอยู่ภายในพาเรนต์ที่เลื่อนได้โดยมีการวางตำแหน่งคงที่ (= ค่าเริ่มต้น)


คุณสามารถทำให้การคำนวณออฟเซ็ตทำงานได้โดยรวม scrollLeft และ scrollTop ไว้ในนั้น
Ben J

แต่ฉันพบoffsetLeftและoffsetTopไม่คำนึงถึงการแปลง CSS3 ซึ่งgetBoundingClientRect()ทำเช่นนั้น นั่นเป็นกรณีที่ผลลัพธ์อาจไม่ถูกต้อง หากคุณจำเป็นต้องใช้มันคุณจะได้รับองค์ประกอบของการชดเชยเมื่อเทียบกับผู้ปกครอง (ชอบoffsetLeft) (element.getBoundingClientRect().left - parent.getBoundingClientRect().left)โดยใช้
Ben J

def ควรจะสูงขึ้น ค่าเหล่านี้มีประโยชน์มากกว่าและทั้งหมดในครั้งเดียวด้วย!
mix3d

7

document-offset( สคริปต์ของบุคคลที่สาม ) เป็นสิ่งที่น่าสนใจและดูเหมือนว่าจะใช้ประโยชน์จากแนวทางอื่น ๆ ที่นี่

ตัวอย่าง:

var offset = require('document-offset')
var target = document.getElementById('target')
console.log(offset(target))
// => {top: 69, left: 108} 

5

ฉันพบว่าวิธีการต่อไปนี้น่าเชื่อถือที่สุดเมื่อจัดการกับ edge case ที่เดินทางขึ้น offsetTop / offsetLeft

function getPosition(element) {
    var clientRect = element.getBoundingClientRect();
    return {left: clientRect.left + document.body.scrollLeft,
            top: clientRect.top + document.body.scrollTop};
}

4

สำหรับผู้ที่ต้องการรับพิกัด x และ y ของตำแหน่งต่างๆขององค์ประกอบโดยสัมพันธ์กับเอกสาร

const getCoords = (element, position) => {
  const { top, left, width, height } = element.getBoundingClientRect();
  let point;
  switch (position) {
    case "top left":
      point = {
        x: left + window.pageXOffset,
        y: top + window.pageYOffset
      };
      break;
    case "top center":
      point = {
        x: left + width / 2 + window.pageXOffset,
        y: top + window.pageYOffset
      };
      break;
    case "top right":
      point = {
        x: left + width + window.pageXOffset,
        y: top + window.pageYOffset
      };
      break;
    case "center left":
      point = {
        x: left + window.pageXOffset,
        y: top + height / 2 + window.pageYOffset
      };
      break;
    case "center":
      point = {
        x: left + width / 2 + window.pageXOffset,
        y: top + height / 2 + window.pageYOffset
      };
      break;
    case "center right":
      point = {
        x: left + width + window.pageXOffset,
        y: top + height / 2 + window.pageYOffset
      };
      break;
    case "bottom left":
      point = {
        x: left + window.pageXOffset,
        y: top + height + window.pageYOffset
      };
      break;
    case "bottom center":
      point = {
        x: left + width / 2 + window.pageXOffset,
        y: top + height + window.pageYOffset
      };
      break;
    case "bottom right":
      point = {
        x: left + width + window.pageXOffset,
        y: top + height + window.pageYOffset
      };
      break;
  }
  return point;
};

การใช้งาน

  • getCoords(document.querySelector('selector'), 'center')

  • getCoords(document.querySelector('selector'), 'bottom right')

  • getCoords(document.querySelector('selector'), 'top center')


2

หากคุณไม่สนใจที่จะใช้ jQuery คุณสามารถใช้offset()ฟังก์ชันได้ โปรดดูเอกสารประกอบหากคุณต้องการอ่านข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันนี้


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.