Получить позицию/смещение элемента относительно родительского контейнера?

Я привык работать с jQuery. Однако в моем текущем проекте я использую zepto.js. Zepto не предоставляет метод position(), например jQuery. Zepto поставляется с offset().

Любая идея, как я могу получить смещение контейнера относительно родителя с чистым js или с Zepto?

Ответ 1

Предупреждение: jQuery, не стандартный JavaScript

element.offsetLeft и element.offsetTop являются чистыми свойствами javascript для нахождения позиции элемента относительно его offsetParent; являющийся ближайшим родительским элементом с позицией relative или absolute

Кроме того, вы всегда можете использовать Zepto, чтобы получить позицию элемента И его родителя, и просто вычесть два:

var childPos = obj.offset();
var parentPos = obj.parent().offset();
var childOffset = {
    top: childPos.top - parentPos.top,
    left: childPos.left - parentPos.left
}

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

Ответ 2

в чистых js просто используйте свойства offsetLeft и offsetTop.
Пример скрипта: http://jsfiddle.net/WKZ8P/

var elm = document.querySelector('span');
console.log(elm.offsetLeft, elm.offsetTop);
p   { position:relative; left:10px; top:85px; border:1px solid blue; }
span{ position:relative; left:30px; top:35px; border:1px solid red; }
<p>
    <span>paragraph</span>
</p>

Ответ 3

Я сделал это в Internet Explorer.

function getWindowRelativeOffset(parentWindow, elem) {
    var offset = {
        left : 0,
        top : 0
    };
    // relative to the target field document
    offset.left = elem.getBoundingClientRect().left;
    offset.top = elem.getBoundingClientRect().top;
    // now we will calculate according to the current document, this current
    // document might be same as the document of target field or it may be
    // parent of the document of the target field
    var childWindow = elem.document.frames.window;
    while (childWindow != parentWindow) {
        offset.left = offset.left + childWindow.frameElement.getBoundingClientRect().left;
        offset.top = offset.top + childWindow.frameElement.getBoundingClientRect().top;
        childWindow = childWindow.parent;
    }

    return offset;
};

=================== вы можете называть это следующим образом

getWindowRelativeOffset(top, inputElement);

Я сосредотачиваюсь на IE только в соответствии с моим фокусом, но подобные вещи могут быть сделаны для других браузеров.

Ответ 4

Добавьте смещение события к смещению родительского элемента, чтобы получить абсолютную позицию смещения события.

Пример:

HTMLElement.addEventListener('mousedown',function(e){

    var offsetX = e.offsetX;
    var offsetY = e.offsetY;

    if( e.target != this ){ // 'this' is our HTMLElement

        offsetX = e.target.offsetLeft + e.offsetX;
        offsetY = e.target.offsetTop + e.offsetY;

    }
}

Когда цель события не является элементом, к которому было зарегистрировано событие, оно добавляет смещение родителя к текущему смещению события, чтобы вычислить значение смещения "Абсолютное".

В соответствии с Mozilla Web API: "Свойство HTMLElement.offsetLeft возвращает только число пикселей, которые в верхнем левом углу текущего элемента смещены влево в элементе HTMLElement.offsetParent node."

Это происходит, когда вы зарегистрировали событие в родительском доме, которое содержит еще несколько дочерних элементов, например: кнопка с внутренним значком или текстом, элемент li с внутренними пролетами. и т.д...

Ответ 5

Пример

Итак, если у нас был дочерний элемент с идентификатором "child-element", и мы хотели получить его left/top position относительно родительского элемента, скажем, div, который имел класс "item-parent", мы будем использовать этот код.

var position = $("#child-element").offsetRelative("div.item-parent");
alert('left: '+position.left+', top: '+position.top);

Плагин Наконец, для фактического плагина (с несколькими заметками, которые показывают, что происходит):

// offsetRelative (or, if you prefer, positionRelative)
(function($){
    $.fn.offsetRelative = function(top){
        var $this = $(this);
        var $parent = $this.offsetParent();
        var offset = $this.position();
        if(!top) return offset; // Didn't pass a 'top' element 
        else if($parent.get(0).tagName == "BODY") return offset; // Reached top of document
        else if($(top,$parent).length) return offset; // Parent element contains the 'top' element we want the offset to be relative to 
        else if($parent[0] == $(top)[0]) return offset; // Reached the 'top' element we want the offset to be relative to 
        else { // Get parent relative offset
            var parent_offset = $parent.offsetRelative(top);
            offset.top += parent_offset.top;
            offset.left += parent_offset.left;
            return offset;
        }
    };
    $.fn.positionRelative = function(top){
        return $(this).offsetRelative(top);
    };
}(jQuery));

Примечание.. Вы можете использовать этот при событии mouseClick или mouseover Event

$(this).offsetRelative("div.item-parent");

Ответ 6

У меня есть другое решение. Вычесть значение родительского свойства из значения дочернего объекта

$('child-div').offset().top - $('parent-div').offset().top;

Ответ 7

Конечно, с чистой JS легко, просто сделайте это, работайте с фиксированными и анимированными панелями HTML 5, я сделал и попробую этот код, и он работает для любого браузера (включая IE 8):

<script type="text/javascript">
    function fGetCSSProperty(s, e) {
        try { return s.currentStyle ? s.currentStyle[e] : window.getComputedStyle(s)[e]; }
        catch (x) { return null; } 
    }
    function fGetOffSetParent(s) {
        var a = s.offsetParent || document.body;

        while (a && a.tagName && a != document.body && fGetCSSProperty(a, 'position') == 'static')
            a = a.offsetParent;
        return a;
    }
    function GetPosition(s) {
        var b = fGetOffSetParent(s);

        return { Left: (b.offsetLeft + s.offsetLeft), Top: (b.offsetTop + s.offsetTop) };
    }    
</script>