Как вычислить координаты html елемента

772
19 декабря 2017, 17:01

Как вычислить (получить) позицию html елемента. offsetTop и offsetLeft даёт относительное значение (не всегда отчёт от точки [x=0,y=0] начала координат). Гугл даёт "недоделаный" вариант http://javascript.ru/ui/offset.

Не "как динамический во время scroll определить текущее местоположение элемента по отношению к родителю", а как получить абсолютные координаты относительно левого верхнего угла содержимого страницы.

Второй вопрос "определить текущее местоположение элемента по отношению к родителю" ещё раз повторяю, абсолютные координаты относительно левого верхнего угла содержимого страницы.

Нужно для "подвешивания" елементов к текущей верстке (что бы вывести на/возле определённого елемента подсказку, сообщение, рекламу и т. п.) например так:

      document.getElementById("act_holder").style.position= "absolute";
      document.getElementById("act_holder").style.display = "block";
      document.getElementById("act_holder").style.top = 
          (getOffset(document.getElementById("act_hlp")).top - 75 ) + "px";    
      document.getElementById("act_holder").innerHTML = "Елемент занят"; 

при использовании absolute нужны координаты относительно левого верхнего угла.

Answer 1

Вот код с javascript.ru собраный до кучи.

function getOffset(elem) {
        if (elem.getBoundingClientRect) {
        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 || body.clientTop || 0;
        var clientLeft = docElem.clientLeft || body.clientLeft || 0;
        return { top: Math.round(box.top +  scrollTop - clientTop), left: Math.round(box.left + scrollLeft - clientLeft) }      
        } else {
             var top=0, left=0
        while(elem) {
            top = top + parseFloat(elem.offsetTop);
            left = left + parseFloat(elem.offsetLeft);
            elem = elem.offsetParent ;
           }
           return {top: top, left: left};
           }
    }

Немного комментариев: ф-ция getBoundingClientRect вызвала спор, mozilla цитата

Возвращаемое значение getBoundingClientRect — это объект TextRectangle, содержащий свойства только для чтения left, top, right и bottom, описывающие бокс с границами в пиксельном измерении. Значения top и left даются относительно верхнего левого угла порта просмотра.

т.е. уже с учётом скролла и отступов документа, которые приходится вычитать если нужны координаты относительно начала системы координат листа (левый верхний угол документа). Даная функция getBoundingClientRect даст верный результат, если выполняется два условия: 1) позиция скроллинга ноль (на старте часто так), 2) если у документа (body) отступы не заданы, или заданы в ноль. Так как эти условия не всегда соблюдены - приходится использывать более сложные решения.

От себя добавлю, что если используется система отчёта position=fixed то getBoundingClientRect выдаст координаты которые подойдут к этой системе отчёта, но fixed редко используется, поскольку при изменении позиции скрола - позиция на экране сохраняется и елемент будет "плавать". А для absolute и static прийдётся делать пересчёт коодинат. Система relative - просто относительные координаты, в отдельных случаях её можно использовать.

Answer 2

Если используется jQuery - то всё просто:

$('#element').offset();//вернёт координаты в формате {top: float, left: float}

Будет работать всегда, кроме fixed-элементов. Это позиция от края документа - позиция внутри страницы.

Answer 3

Кликни на любой элемент получишь данные Объясни, какие ты еще хочешь получить координаты абсолютные??? Вполне вероятно, что пойму... Смотреть лучше на весь экран

var wrapper = document.getElementById('wrapper'); 
var infomBlock = document.getElementById('infomBlock'); 
var blocks = document.getElementsByClassName('blocks'); 
 
function getСoordinates(elem) { 
  return coord = [ 
    'это абсолютное значени нижней границы элемента от окна просмотра - bottom ' + elem.getBoundingClientRect().bottom, 
    '<br/>это абсолютное значени верхней  границы элемента от окна просмотра - top ' + elem.getBoundingClientRect().top, 
    '<br/> это абсолютное значени левой границы элемента от окна просмотра - left ' + elem.getBoundingClientRect().left, 
    '<br/>right это абсолютное значени правой границы элемента от окна просмотра - ' + elem.getBoundingClientRect().right, 
    '<br/>height - это абсолютное значени высоты элемента ' + elem.getBoundingClientRect().height, 
    '<br/>width - это абсолютное значени ширины элемента ' + elem.getBoundingClientRect().width, 
    '<br/>x - это абсолютное значени верхнего левого угла элемента по координате х' + elem.getBoundingClientRect().x, 
    '<br/>y - это абсолютное значени верхнего левого угла элемента по координате y ' + elem.getBoundingClientRect().y, 
  ]; 
 
  console.log(...coord) 
 
} 
 
for (var i = 0; i < blocks.length; i++) { 
  blocks[i].addEventListener('click', function() { 
    getСoordinates(this); 
    infomBlock.innerHTML = coord; 
  }) 
}
* { 
  margin: 0; 
  padding: 0; 
} 
 
html, 
body { 
  width: 100%; 
  height: 100%; 
  background: #272727; 
} 
 
#wrapper { 
  color: white; 
  width: 100%; 
  height: 100%; 
} 
 
#infomBlock.blocks { 
  display: block; 
  margin: 0; 
  background: rgba(200, 200, 200, .5); 
  width: 100%; 
  height: 200px; 
  color: white; 
} 
 
.blocks { 
  cursor: pointer; 
  display: inline-block; 
  margin: 50px 20px; 
  color: white; 
  width: 150px; 
  height: 150px; 
  background: orange; 
} 
 
.blocks:nth-child(even) { 
  margin: 150px 10px; 
}
<div id="wrapper"> 
  <div id="infomBlock" class="blocks"></div> 
  <div class="blocks"></div> 
  <div class="blocks"></div> 
  <div class="blocks"></div> 
  <div class="blocks"></div> 
  <div class="blocks"></div> 
  <div class="blocks"></div> 
  <div class="blocks"></div> 
</div>

READ ALSO
Как добавить информацию на страницу, но не показывать ее?

Как добавить информацию на страницу, но не показывать ее?

На странице (html) выводятся события календаря в виде div, данные получаю по REST через ajaxХочется сделать, чтобы по клику на каждое событие всплывало...

213
Приходят пустые html письма

Приходят пустые html письма

При отправки html писем, на некоторых моделях iphone приходят пустыеСмотрю с iphone 4, все нормально, iphone 8 и iphone 8+ письма пустые, если пустое письмо...

165
Панель закладок в несколько строк для Firefox 57/58? [требует правки]

Панель закладок в несколько строк для Firefox 57/58? [требует правки]

Для firefox quantom пока не существует расширения для многострочных вкладок как Multirow bookmarks toolbarА как сделать такое без установки расширения ?

531