Tìm vị trí của phần tử so với tài liệu


113

Cách dễ nhất để xác định vị trí phần tử so với cửa sổ tài liệu / nội dung / trình duyệt là gì?

Hiện tôi đang sử dụng .offsetLeft/offsetTop, nhưng phương pháp này chỉ cung cấp cho bạn vị trí liên quan đến phần tử cha, vì vậy bạn cần xác định có bao nhiêu phần tử cha đối với phần tử body, để biết vị trí liên quan đến vị trí phần thân / cửa sổ trình duyệt / tài liệu.

Phương pháp này cũng là để rườm rà.

Câu trả lời:


60

Bạn có thể xem qua offsetParentcấp cao nhất của DOM.

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

28
Không, không, khi bất kỳ cha mẹ nào (đặc biệt là phần tử html !!!) có lề, đệm hoặc đường viền.
Flash Thunder

liên quan đến các công cụ lề ... nó có thể giúp thiết lập các hộp kích thước đến biên giới-box ... hoặc một cái gì đó dọc theo những đường ... không có gì mà không thể được cố định ...

Đầu tiên, bạn cần quyết định xem có tính đến đường viền và lề theo kích thước hộp hay không. Thứ hai, lợi nhuận bị thu hẹp nên được xem xét. Và cuối cùng, sẽ có nhiều tình huống phức tạp hơn trong tương lai khiến câu trả lời này trở nên tồi tệ hơn.
xianshenglu

5
Tại sao đây là câu trả lời được chấp nhận? Điều này đã lỗi thời và hoạt động kém. Hãy tự giúp mình và sử dụng getBoundsClientRect () như được đề xuất trong các câu trả lời khác.
Fabian von Ellerts

175

Bạn có thể lên trênsang trái mà không cần lướt qua DOM như thế này:

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
Câu trả lời này không tính đến phần bù của cha mẹ. Nó chỉ liên quan đến các khung nhìn
Nickey

3
@Nickey không đúng — vị trí khung nhìn, cộng với các kiểm tra độ lệch cuộn, mang lại tọa độ liên quan đến toàn bộ tài liệu.
natchiketa

1
Có thể gặp lỗi trên thiết bị di động stackoverflow.com/a/32623832/962634 Cần nghiên cứu
húng quế

1
Tại sao bạn lại trừ clientTop / clientLeft?
Teemoh

1
@Teemoh clientTop / clientLeft tương ứng với các giá trị đường viền trên <html>phần tử.
Raphael Rafatpanah

98

Bạn có thể sử dụng element.getBoundingClientRect()để truy xuất vị trí phần tử liên quan đến chế độ xem.

Sau đó, sử dụng document.documentElement.scrollTopđể tính toán độ lệch khung nhìn.

Tổng của hai sẽ cung cấp vị trí phần tử liên quan đến tài liệu:

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

10
Tương đối với khung nhìn không giống với liên quan đến tài liệu. Nếu trang được cuộn xuống một chút thì phần trên cùng so với chế độ xem sẽ là một số nhỏ hơn phần trên cùng so với tài liệu.
MrVimes

14
anh ta bắt đầu tương đối với khung nhìn và thêm scrollY để đưa nó liên quan đến tài liệu.
Joaquin Cuenca Abela

2
document.documentElement.scrollTopkhông hoạt động trong Safari, sử dụng window.scrollYthay vì
Fabian von Ellerts

7

Tôi đề nghị sử dụng

element.getBoundingClientRect()

như được đề xuất ở đây thay vì tính toán bù đắp thủ công thông qua offsetLeft , offsetTopoffsetParent . như được đề xuất ở đây Trong một số trường hợp * truyền tải thủ công tạo ra kết quả không hợp lệ. Xem Plunker này: http://plnkr.co/pC8Kgj

* Khi phần tử nằm bên trong phần tử gốc có thể cuộn với định vị tĩnh (= mặc định).


Bạn cũng có thể làm cho phép tính bù đắp hoạt động bằng cách kết hợp scrollLeft và scrollTop vào nó.
Ben J

Nhưng tôi đã tìm thấy offsetLeftoffsetTopkhông tính đến các chuyển đổi CSS3 getBoundingClientRect(). Vì vậy, đó là một trường hợp kết quả có thể không hợp lệ. Nếu cần, bạn có thể lấy phần tử bù đắp tương đối với phần tử gốc (như offsetLeft) bằng cách sử dụng (element.getBoundingClientRect().left - parent.getBoundingClientRect().left).
Ben J

def nên lên cao hơn; những giá trị này hữu ích hơn nhiều và tất cả trong một lần gọi!
mix3d

7

document-offset( Tập lệnh của bên thứ 3 ) rất thú vị và nó dường như tận dụng các phương pháp tiếp cận từ các câu trả lời khác ở đây.

Thí dụ:

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

5

Tôi đã tìm thấy phương pháp sau đây là đáng tin cậy nhất khi xử lý các trường hợp cạnh tăng lên offsetTop / offsetLeft.

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

4

Đối với những người muốn lấy tọa độ x và y của các vị trí khác nhau của một phần tử, liên quan đến tài liệu.

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;
};

Sử dụng

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

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

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


2

Nếu bạn không phiền khi sử dụng jQuery, thì bạn có thể sử dụng offset()hàm. Tham khảo tài liệu nếu bạn muốn đọc thêm về chức năng này.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.