javascript - tutorial - Recupera la posizione(X, Y) di un elemento HTML




libreria ajax (16)

Ottieni la posizione di div rispetto a sinistra e superiore

  var elm = $('#div_id');  //get the div
  var posY_top = elm.offset().top;  //get the position from top
  var posX_left = elm.offset().left; //get the position from left 

Voglio sapere come ottenere la posizione X e Y degli elementi HTML come img e div in JavaScript.


È possibile aggiungere due proprietà a Element.prototype per ottenere la parte superiore / sinistra di qualsiasi elemento.

Object.defineProperty( Element.prototype, 'documentOffsetTop', {
    get: function () { 
        return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop : 0 );
    }
} );

Object.defineProperty( Element.prototype, 'documentOffsetLeft', {
    get: function () { 
        return this.offsetLeft + ( this.offsetParent ? this.offsetParent.documentOffsetLeft : 0 );
    }
} );

Questo è chiamato così:

var x = document.getElementById( 'myDiv' ).documentOffsetLeft;

Ecco una demo che confronta i risultati con l' offset().top di jQuery offset().top e .left : http://jsfiddle.net/ThinkingStiff/3G7EZ/


Dal momento che i vari browser stanno rendendo il bordo, il padding, il margine e così via in modo diverso. Ho scritto una piccola funzione per recuperare le posizioni superiore e sinistra dell'elemento specifico in ogni elemento radice che desideri in una dimensione precisa:

function getTop(root, offset) {
    var rootRect = root.getBoundingClientRect();
    var offsetRect = offset.getBoundingClientRect();
    return offsetRect.top - rootRect.top;
}

Per recuperare la posizione a sinistra è necessario tornare:

    return offsetRect.left - rootRect.left;

Differenza tra piccolo e piccolo

function getPosition( el ) {
    var x = 0;
    var y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
    x += el.offsetLeft - el.scrollLeft;
    y += el.offsetTop - el.scrollTop;
    el = el.offsetParent;
    }
    return { top: y, left: x };
}

Guarda le coordinate di un esempio: http://javascript.info/tutorial/coordinates


Gli elementi HTML sulla maggior parte dei browser avranno: -

offsetLeft
offsetTop

Questi specificano la posizione dell'elemento rispetto al genitore più vicino che ha il layout. È spesso possibile accedere a questo elemento principale bif la proprietà offsetParent.

IE e FF3 hanno

clientLeft
clientTop

Queste proprietà sono meno comuni, specificano una posizione di elementi con l'area client dei genitori (l'area riempita fa parte dell'area client ma il bordo e il margine non lo sono).


Ho pensato di buttarlo anche lì.
Non sono stato in grado di testarlo nei browser più vecchi, ma funziona nell'ultimo dei primi 3. :)

Element.prototype.getOffsetTop = function() {
    return ( this.parentElement )? this.offsetTop + this.parentElement.getOffsetTop(): this.offsetTop;
};
Element.prototype.getOffsetLeft = function() {
    return ( this.parentElement )? this.offsetLeft + this.parentElement.getOffsetLeft(): this.offsetLeft;
};
Element.prototype.getOffset = function() {
    return {'left':this.getOffsetLeft(),'top':this.getOffsetTop()};
};

Ho usato con successo la soluzione di Andy E per posizionare un modal bootstrap 2 a seconda del collegamento in una riga della tabella su cui un utente fa clic. La pagina è una pagina Tapestry 5 e javascript di seguito viene importata nella classe java page.

javascript:

function setLinkPosition(clientId){
var bodyRect = document.body.getBoundingClientRect(),
elemRect = clientId.getBoundingClientRect(),
offset   = elemRect.top - bodyRect.top;
offset   = offset + 20;
$('#serviceLineModal').css("top", offset);

}

Il mio codice modale:

<div id="serviceLineModal" class="modal hide fade add-absolute-position" data-backdrop="static" 
 tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="top:50%;">
<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
    <h3 id="myModalLabel">Modal header</h3>
</div>

<div class="modal-body">
    <t:zone t:id="modalZone" id="modalZone">
        <p>You selected service line number: ${serviceLineNumberSelected}</p>
    </t:zone>
</div>

<div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <!-- <button class="btn btn-primary">Save changes</button> -->
</div>

Il link nel loop:

<t:loop source="servicesToDisplay" value="service" encoder="encoder">
<tr style="border-right: 1px solid black;">       
    <td style="white-space:nowrap;" class="add-padding-left-and-right no-border"> 
        <a t:type="eventLink" t:event="serviceLineNumberSelected" t:context="service.serviceLineNumber" 
            t:zone="pageZone" t:clientId="modalLink${service.serviceLineNumber}"
            onmouseover="setLinkPosition(this);">
            <i class="icon-chevron-down"></i> <!-- ${service.serviceLineNumber} -->
        </a>
    </td>

E il codice java nella classe di pagina:

void onServiceLineNumberSelected(String number){
    checkForNullSession();
    serviceLineNumberSelected = number;
    addOpenServiceLineDialogCommand();
    ajaxResponseRenderer.addRender(modalZone);
}

protected void addOpenServiceLineDialogCommand() {
    ajaxResponseRenderer.addCallback(new JavaScriptCallback() {
        @Override
        public void run(JavaScriptSupport javascriptSupport) {
            javascriptSupport.addScript("$('#serviceLineModal').modal('show');");
        }
    });
}

Spero che questo aiuti qualcuno, questo post ha aiutato.


L'approccio corretto è usare element.getBoundingClientRect() :

var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);

Internet Explorer lo ha supportato fino a quando è probabile che ti interessi e alla fine è stato standardizzato nelle viste CSSOM . Tutti gli altri browser l'hanno adottata molto tempo fa .

Alcuni browser restituiscono anche le proprietà di altezza e larghezza, sebbene questo non sia standard. Se sei preoccupato per la compatibilità del browser precedente, controlla le revisioni di questa risposta per un'implementazione degradante ottimizzata.

I valori restituiti da element.getBoundingClientRect() sono relativi al viewport. Se ne hai bisogno relativamente ad un altro elemento, semplicemente sottrai un rettangolo dall'altro:

var bodyRect = document.body.getBoundingClientRect(),
    elemRect = element.getBoundingClientRect(),
    offset   = elemRect.top - bodyRect.top;

alert('Element is ' + offset + ' vertical pixels from <body>');

L'ho fatto in questo modo, quindi era cross-compatibile con i vecchi browser.

// For really old browser's or incompatible ones
    function getOffsetSum(elem) {
        var top = 0,
            left = 0,
            bottom = 0,
            right = 0

         var width = elem.offsetWidth;
         var height = elem.offsetHeight;

        while (elem) {
            top += elem.offsetTop;
            left += elem.offsetLeft;
            elem = elem.offsetParent;
        }

         right = left + width;
         bottom = top + height;

        return {
            top: top,
            left: left,
            bottom: bottom,
            right: right,
        }
    }

    function getOffsetRect(elem) {
        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;
        var clientLeft = docElem.clientLeft;


        var top = box.top + scrollTop - clientTop;
        var left = box.left + scrollLeft - clientLeft;
        var bottom = top + (box.bottom - box.top);
        var right = left + (box.right - box.left);

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

    function getOffset(elem) {
        if (elem) {
            if (elem.getBoundingClientRect) {
                return getOffsetRect(elem);
            } else { // old browser
                return getOffsetSum(elem);
            }
        } else
            return null;
    }

Maggiori informazioni sulle coordinate in JavaScript qui: http://javascript.info/tutorial/coordinates


Le librerie fanno di tutto per ottenere correzioni accurate per un elemento.
ecco una semplice funzione che fa il lavoro in ogni circostanza che ho provato.

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}
var x = getOffset( document.getElementById('yourElId') ).left; 

Per recuperare la posizione relativa alla pagina in modo efficiente e senza utilizzare una funzione ricorsiva: (include anche IE)

var element = document.getElementById('elementId'); //replace elementId with your element's Id.
var rect = element.getBoundingClientRect();
var elementLeft,elementTop; //x and y
var scrollTop = document.documentElement.scrollTop?
                document.documentElement.scrollTop:document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft?                   
                 document.documentElement.scrollLeft:document.body.scrollLeft;
elementTop = rect.top+scrollTop;
elementLeft = rect.left+scrollLeft;

Questo è il codice migliore che sono riuscito a creare (funziona anche negli iframe, a differenza dell'offset di jQuery ()). Sembra che il webkit abbia un comportamento un po 'diverso.

Basato sul commento di meouw:

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        // chrome/safari
        if ($.browser.webkit) {
            el = el.parentNode;
        } else {
            // firefox/IE
            el = el.offsetParent;
        }
    }
    return { top: _y, left: _x };
}

Se la pagina include - almeno - qualsiasi "DIV", la funzione data da meouw lancia il valore "Y" oltre i limiti della pagina corrente. Per trovare la posizione esatta, devi gestire sia offsetParent che parentNode.

Prova il codice indicato di seguito (è controllato per FF2):


var getAbsPosition = function(el){
    var el2 = el;
    var curtop = 0;
    var curleft = 0;
    if (document.getElementById || document.all) {
        do  {
            curleft += el.offsetLeft-el.scrollLeft;
            curtop += el.offsetTop-el.scrollTop;
            el = el.offsetParent;
            el2 = el2.parentNode;
            while (el2 != el) {
                curleft -= el2.scrollLeft;
                curtop -= el2.scrollTop;
                el2 = el2.parentNode;
            }
        } while (el.offsetParent);

    } else if (document.layers) {
        curtop += el.y;
        curleft += el.x;
    }
    return [curtop, curleft];
};


Se si utilizza jQuery, questa potrebbe essere una soluzione semplice:

<script>
  var el = $("#element");
  var position = el.position();
  console.log( "left: " + position.left + ", top: " + position.top );
</script>

Si potrebbe essere meglio serviti utilizzando un framework JavaScript, che ha funzioni per restituire tali informazioni (e molto altro ancora!) In modo indipendente dal browser. Eccone alcuni:

Con questi framework, si potrebbe fare qualcosa come: $('id-of-img').top per ottenere la coordinata y-pixel dell'immagine.


jQuery .offset() otterrà le coordinate correnti del primo elemento, o imposta le coordinate di ogni elemento, nel set di elementi abbinati, relativo al documento.







position