Desejo obter a posição de um elemento em relação à viewport do navegador (a viewport na qual a página é exibida, não a página inteira). Como isso pode ser feito em JavaScript?
Muito Obrigado
Desejo obter a posição de um elemento em relação à viewport do navegador (a viewport na qual a página é exibida, não a página inteira). Como isso pode ser feito em JavaScript?
Muito Obrigado
Respostas:
As respostas existentes agora estão desatualizadas. O getBoundingClientRect()método nativo já existe há algum tempo e faz exatamente o que a pergunta pede. Além disso, ele é suportado em todos os navegadores (incluindo o IE 5, ao que parece!)
Na página MDN :
O valor retornado é um objeto TextRectangle, que contém propriedades esquerda, superior, direita e inferior somente leitura que descrevem a caixa de borda, em pixels, com a parte superior esquerda relativa à parte superior esquerda da janela de visualização .
Você usa assim:
var viewportOffset = el.getBoundingClientRect();
// these are relative to the viewport, i.e. the window
var top = viewportOffset.top;
var left = viewportOffset.left;
getBoundingClientRect().topnão está no meu IE11, retorna 0. Você tem alguma solução.
No meu caso, apenas para garantir a rolagem, adicionei o window.scroll à equação:
var element = document.getElementById('myElement');
var topPos = element.getBoundingClientRect().top + window.scrollY;
var leftPos = element.getBoundingClientRect().left + window.scrollX;
Isso me permite obter a posição relativa real do elemento no documento, mesmo que ele tenha sido rolado.
getBoundingClientRect().topnão está no meu IE11, ele retorna 0. Você tem alguma solução.
window.scrollY || window.pageYOffsetpode melhorar o suporte
Editar: adicione algum código para explicar a rolagem da página.
function findPos(id) {
var node = document.getElementById(id);
var curtop = 0;
var curtopscroll = 0;
if (node.offsetParent) {
do {
curtop += node.offsetTop;
curtopscroll += node.offsetParent ? node.offsetParent.scrollTop : 0;
} while (node = node.offsetParent);
alert(curtop - curtopscroll);
}
}
O argumento id é o id do elemento cujo deslocamento você deseja. Adaptado de uma postagem de modo quirks .
var element = document.querySelector('selector');
var bodyRect = document.body.getBoundingClientRect(),
elemRect = element.getBoundingClientRect(),
offset = elemRect.top - bodyRect.top;
Podes tentar:
node.offsetTop - window.scrollY
Funciona no Opera com a meta tag da viewport definida.
offsetTopé relativa ao elemento posicionado mais próximo. Que, dependendo da estrutura da página, pode ou não ser elemento raiz.
O jQuery implementa isso de maneira bastante elegante. Se você procurar a fonte para jQuery offset, verá que é basicamente assim que é implementado:
var rect = elem.getBoundingClientRect();
var win = elem.ownerDocument.defaultView;
return {
top: rect.top + win.pageYOffset,
left: rect.left + win.pageXOffset
};
A função nesta página retornará um retângulo com as coordenadas superior, esquerda, altura e largura de um elemento passado em relação à porta de visualização do navegador.
localToGlobal: function( _el ) {
var target = _el,
target_width = target.offsetWidth,
target_height = target.offsetHeight,
target_left = target.offsetLeft,
target_top = target.offsetTop,
gleft = 0,
gtop = 0,
rect = {};
var moonwalk = function( _parent ) {
if (!!_parent) {
gleft += _parent.offsetLeft;
gtop += _parent.offsetTop;
moonwalk( _parent.offsetParent );
} else {
return rect = {
top: target.offsetTop + gtop,
left: target.offsetLeft + gleft,
bottom: (target.offsetTop + gtop) + target_height,
right: (target.offsetLeft + gleft) + target_width
};
}
};
moonwalk( target.offsetParent );
return rect;
}
function inViewport(element) {
let bounds = element.getBoundingClientRect();
let viewWidth = document.documentElement.clientWidth;
let viewHeight = document.documentElement.clientHeight;
if (bounds['left'] < 0) return false;
if (bounds['top'] < 0) return false;
if (bounds['right'] > viewWidth) return false;
if (bounds['bottom'] > viewHeight) return false;
return true;
}
Obrigado por todas as respostas. Parece que o Prototype já possui uma função que faz isso (a função page ()). Ao visualizar o código fonte da função, descobri que ela primeiro calcula a posição do deslocamento do elemento em relação à página (ou seja, a parte superior do documento) e depois subtrai o scrollTop a partir dela. Veja o código fonte do protótipo para mais detalhes.
Estou assumindo que btn1existe um elemento com um ID na página da Web e também que o jQuery está incluído. Isso funcionou em todos os navegadores modernos do Chrome, FireFox, IE> = 9 e Edge. O jQuery está sendo usado apenas para determinar a posição em relação ao documento.
var screenRelativeTop = $("#btn1").offset().top - (window.scrollY ||
window.pageYOffset || document.body.scrollTop);
var screenRelativeLeft = $("#btn1").offset().left - (window.scrollX ||
window.pageXOffset || document.body.scrollLeft);
Às vezes, getBoundingClientRect()o valor da propriedade do objeto mostra 0 para o IE. Nesse caso, você deve definir display = 'block'o elemento. Você pode usar o código abaixo para que todo o navegador seja compensado.
Estenda a funcionalidade jQuery:
(function($) {
jQuery.fn.weOffset = function () {
var de = document.documentElement;
$(this).css("display", "block");
var box = $(this).get(0).getBoundingClientRect();
var top = box.top + window.pageYOffset - de.clientTop;
var left = box.left + window.pageXOffset - de.clientLeft;
return { top: top, left: left };
};
}(jQuery));
Usar :
var elementOffset = $("#" + elementId).weOffset();