Получить реальное смещение слева / сверху элемента с помощью встроенного родительского смещения - PullRequest
5 голосов
/ 28 марта 2011

Я пытаюсь получить координаты элемента на странице. Я использовал стандартный способ получить его:

var el = element, pos = {x: 0, y: 0};
while ( el ) {
    pos.x += el.offsetLeft;
    pos.y += el.offsetTop;
    el = el.offsetParent;
}

Но этот метод завершается ошибкой, если у рассматриваемого элемента display: block, а у одного из offsetParents - display: inline;. Это связано с тем, что описано в этой теме :

The element starts in the middle of the text

После некоторых попыток с jQuery оказывается, что их .offset() -метод возвращает правильное смещение, и я просмотрел источник, но не нашел точно, как они это делают. Итак, мой вопрос: как я могу получить точную позицию? Я не могу использовать jQuery для этого проекта, и метод в описанном ранее потоке является громоздким, добавление элемента и тестирование - это слишком много работы (с точки зрения производительности), а использование Element.getBoundingClientRect недоступно либо.

Если вы хотите попробовать его, перейдите на Apple.com , откройте выбранный отладчик и введите следующее:

var el, el2;
el = el2 = document.querySelector('#worldwide span');
var pos = {x: 0, y: 0};
while ( el2 ) {
    pos.x += el2.offsetLeft;
    pos.y += el2.offsetTop;
    el2 = el2.offsetParent;
}
alert("Calculated position: " + pos.x + "x" + pos.y + " window size: " + screen.width + "x" + screen.height);

С этим кодом я получаю: Calculated position: 1354x988 window size: 1280x800 (т.е. смещение влево - это путь экрана, которого он явно не имеет)

Как это возможно? Какие-нибудь обходные идеи? Аппроксимация? Оно не должно быть точным, но оно должно быть лучше, чем раньше. Спасибо.

Редактировать: это для механизма рендеринга WebKit, чтобы уточнить.

Ответы [ 4 ]

2 голосов
/ 02 апреля 2011

Я закончил тем, что пошел с WebKit window.webkitConvertPointFromNodeToPage, но я продолжал сталкиваться с ошибкой, когда она возвращала позицию, которая была полностью неправильной. Дальнейшее исследование показало, что если рассматриваемый узел был отображен: inline, то он вернул бы позицию последнего элемента блока в иерархии.

Поиск разрешения для этого изображения ничего не дал (все, что я нашел, было очень простой информацией о том, что на самом деле сделал webkitConvertPointFromNodeToPage, и исходный код WebKit).

Догадываясь, я обнаружил, что он вернул правильную позицию, если элемент имел display: inline-block, поэтому, если элемент был встроенным, я изменил его на inline-block и затем вычислил позицию.

Если у кого-то есть лучшее решение этой проблемы, я бы хотел услышать от вас!

Edit:

Оказывается, изменение стиля отображения на встроенный блок не всегда хорошая идея, поэтому вместо этого я использую этот метод:

var offset = {x: 0, y: 0};
if ( getStyle(el, 'display') == 'inline' ) {
    offset.x = el.offsetLeft - el.parentNode.offsetLeft;
    offset.y = el.offsetTop - el.parentNode.offsetTop;
}

var point = window.webkitConvertPointFromNodeToPage(el, new WebKitPoint(0, 0));

return {
    x: Math.round(point.x + offset.x),
    y: Math.round(point.y + offset.y)
}

Я беру встроенный дочерний метод offsetTop / Left и вычитаю его из родительского элемента. Я не совсем уверен, как это работает с родителями, у которых есть дисплей: встроенный, но он работает 90% времени.

Но если у кого-то есть идея получше, я все еще открыт для предложений.

1 голос
/ 06 января 2014

У меня была та же проблема. При использовании $.offset().left с jQuery попытка получить положение слова в абзаце.

Использование $.offset().left внутри функции $(document).ready() дало неверный результат.

Использование $.offset().left в функции $(window).load() решило мою проблему в WebKit.

Это особенно актуально, когда могут быть плавающие элементы изображения или шрифты, которые будут влиять на макет.

1 голос
/ 10 апреля 2013

Изучение исходного кода webkitConvertPointFromNodeToPage показывает, что он вычисляет с использованием объекта средства визуализации элементов, и если такого средства визуализации не существует, он использует родителя-предшественника, у которого есть средство визуализации. Однако, когда используется средство визуализации предка, оно не корректирует смещение, чтобы учесть разницу в источнике между целью и источником ее предка. Это означает, что функция работает правильно, когда точка задана относительно содержащего средства визуализации. Если элемент, для которого вы рассчитываете координаты, не имеет средства визуализации, вам нужно вручную отрегулировать смещение до ближайшего предка, у которого оно есть (с помощью offsetLeft / Top). Чтобы точно знать, какие элементы имеют средства визуализации, потребуется больше исследований, но обычно любой элемент, который не имеет содержимого, но влияет на отображение других узлов, таких как SPAN, не нуждается в устройстве визуализации.

1 голос
/ 28 марта 2011

Возможно здесь вы найдете описание идей, использованных в исходном коде jQuery.offset .

Если вы посмотрите здесь вы можете видеть, что offsetLeft и offsetTop работают не совсем корректно в старых версиях IE.

Я понимаю, что интересно понять, как можно реализовать эти или другие вещи.Как вы видите исходный код функции jQuery.offset не так просто.Если вы хотите, чтобы ваш код работал правильно и не зависел от браузера, вам лучше просто использовать jQuery.offset вместо написания собственной реализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...