javascript - slow - Compruebe si el elemento es visible después de desplazarse
scroll jquery ejemplos (30)
Estoy cargando elementos a través de AJAX. Algunos de ellos solo son visibles si se desplaza hacia abajo en la página.
¿Hay alguna manera de saber si un elemento está ahora en la parte visible de la página?
Adapté esta corta extensión de la función jQuery, que puedes usar libremente (licencia MIT).
/**
* returns true if an element is visible, with decent performance
* @param [scope] scope of the render-window instance; default: window
* @returns {boolean}
*/
jQuery.fn.isOnScreen = function(scope){
var element = this;
if(!element){
return;
}
var target = $(element);
if(target.is('':visible'') == false){
return false;
}
scope = $(scope || window);
var top = scope.scrollTop();
var bot = top + scope.height();
var elTop = target.offset().top;
var elBot = elTop + target.height();
return ((elBot <= bot) && (elTop >= top));
};
Aprovechando esta gran respuesta , puede simplificarla un poco más con ES2015 +:
function isScrolledIntoView(el) {
const { top, bottom } = el.getBoundingClientRect()
return top >= 0 && bottom <= window.innerHeight
}
Si no te importa que la ventana salga por la ventana y te importa que se haya visto la parte inferior, esto se puede simplificar para
function isSeen(el) {
return el.getBoundingClientRect().bottom <= window.innerHeight
}
o incluso el de una sola línea
const isSeen = el => el.getBoundingClientRect().bottom <= window.innerHeight
Aquí está mi solución de JavaScript pura que funciona si también está oculta dentro de un contenedor desplazable.
Demo aquí (intente cambiar el tamaño de la ventana también)
var visibleY = function(el){
var rect = el.getBoundingClientRect(), top = rect.top, height = rect.height,
el = el.parentNode
// Check if bottom of the element is off the page
if (rect.bottom < 0) return false
// Check its within the document viewport
if (top > document.documentElement.clientHeight) return false
do {
rect = el.getBoundingClientRect()
if (top <= rect.bottom === false) return false
// Check if the element is out of view due to a container scrolling
if ((top + height) <= rect.top) return false
el = el.parentNode
} while (el != document.body)
return true
};
EDITAR 2016-03-26: Actualicé la solución para tener en cuenta el desplazamiento más allá del elemento para que esté oculto en la parte superior del contenedor con capacidad de desplazamiento. EDITAR 2018-10-08: actualizado para manejar cuando se desplaza fuera de la vista sobre la pantalla.
Aquí hay otra solución de http://web-profile.com.ua/
<script type="text/javascript">
$.fn.is_on_screen = function(){
var win = $(window);
var viewport = {
top : win.scrollTop(),
left : win.scrollLeft()
};
viewport.right = viewport.left + win.width();
viewport.bottom = viewport.top + win.height();
var bounds = this.offset();
bounds.right = bounds.left + this.outerWidth();
bounds.bottom = bounds.top + this.outerHeight();
return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};
if( $(''.target'').length > 0 ) { // if target element exists in DOM
if( $(''.target'').is_on_screen() ) { // if target element is visible on screen after DOM loaded
$(''.log'').html(''<div class="alert alert-success">target element is visible on screen</div>''); // log info
} else {
$(''.log'').html(''<div class="alert">target element is not visible on screen</div>''); // log info
}
}
$(window).scroll(function(){ // bind window scroll event
if( $(''.target'').length > 0 ) { // if target element exists in DOM
if( $(''.target'').is_on_screen() ) { // if target element is visible on screen after DOM loaded
$(''.log'').html(''<div class="alert alert-success">target element is visible on screen</div>''); // log info
} else {
$(''.log'').html(''<div class="alert">target element is not visible on screen</div>''); // log info
}
}
});
</script>
Aquí hay una manera de lograr lo mismo usando Mootools, en horizontal, vertical o ambos.
Element.implement({
inVerticalView: function (full) {
if (typeOf(full) === "null") {
full = true;
}
if (this.getStyle(''display'') === ''none'') {
return false;
}
// Window Size and Scroll
var windowScroll = window.getScroll();
var windowSize = window.getSize();
// Element Size and Scroll
var elementPosition = this.getPosition();
var elementSize = this.getSize();
// Calculation Variables
var docViewTop = windowScroll.y;
var docViewBottom = docViewTop + windowSize.y;
var elemTop = elementPosition.y;
var elemBottom = elemTop + elementSize.y;
if (full) {
return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
&& (elemBottom <= docViewBottom) && (elemTop >= docViewTop) );
} else {
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
},
inHorizontalView: function(full) {
if (typeOf(full) === "null") {
full = true;
}
if (this.getStyle(''display'') === ''none'') {
return false;
}
// Window Size and Scroll
var windowScroll = window.getScroll();
var windowSize = window.getSize();
// Element Size and Scroll
var elementPosition = this.getPosition();
var elementSize = this.getSize();
// Calculation Variables
var docViewLeft = windowScroll.x;
var docViewRight = docViewLeft + windowSize.x;
var elemLeft = elementPosition.x;
var elemRight = elemLeft + elementSize.x;
if (full) {
return ((elemRight >= docViewLeft) && (elemLeft <= docViewRight)
&& (elemRight <= docViewRight) && (elemLeft >= docViewLeft) );
} else {
return ((elemRight <= docViewRight) && (elemLeft >= docViewLeft));
}
},
inView: function(full) {
return this.inHorizontalView(full) && this.inVerticalView(full);
}});
El mejor método que he encontrado hasta ahora es el complemento jQuery aparecen . Funciona de maravilla.
Imita un evento "aparece" personalizado, que se activa cuando un elemento se desplaza a la vista o se vuelve visible para el usuario.
$(''#foo'').appear(function() { $(this).text(''Hello world''); });
Este complemento se puede usar para evitar solicitudes innecesarias de contenido oculto o fuera del área visible.
El plugin jQuery Waypoints va muy bien aquí.
$(''.entry'').waypoint(function() {
alert(''You have scrolled to an entry.'');
});
Hay algunos ejemplos en el sitio del complemento .
El uso de la nueva API IntersectionObserver es muy fácil y eficiente para determinar si un elemento es visible en la ventana gráfica. Al usar un observador , elimina la necesidad de adjuntar un evento de scroll
y verificar manualmente la devolución de llamada del evento.
// this is the target which is observed
var target = document.querySelector(''div'');
// configure the intersection observer instance
var intersectionObserverOptions = {
root: null,
rootMargin: ''150px'',
threshold: 1.0
}
var observer = new IntersectionObserver(onIntersection, intersectionObserverOptions);
// provice the observer with a target
observer.observe(target);
function onIntersection(entries){
entries.forEach(entry => {
console.clear();
console.log(entry.intersectionRatio)
target.classList.toggle(''visible'', entry.intersectionRatio > 0);
// Are we in viewport?
if (entry.intersectionRatio > 0) {
// Stop watching
// observer.unobserve(entry.target);
}
});
}
.box{ width:100px; height:100px; background:red; margin:1000px; }
.box.visible{ background:green; }
Scroll both Vertically & Horizontally...
<div class=''box''></div>
Ver tabla de compatibilidad de navegadores (no se admite en IE / Safari)
Estaba buscando una manera de ver si el elemento se mostrará pronto, por lo que al extender los fragmentos arriba, logré hacerlo. Pensé que dejaría esto aquí en caso de que ayude a alguien
elm = es el elemento que desea verificar está en la vista
scrollElement = puede pasar una ventana o un elemento padre que tiene un desplazamiento
offset = si desea que se dispare cuando el elemento está a 200 px de distancia antes de que aparezca en la pantalla, pase 200
function isScrolledIntoView(elem, scrollElement, offset)
{
var $elem = $(elem);
var $window = $(scrollElement);
var docViewTop = $window.scrollTop();
var docViewBottom = docViewTop + $window.height();
var elemTop = $elem.offset().top;
var elemBottom = elemTop + $elem.height();
return (((elemBottom+offset) >= docViewBottom) && ((elemTop-offset) <= docViewTop)) || (((elemBottom-offset) <= docViewBottom) && ((elemTop+offset) >= docViewTop));
}
Este método devolverá verdadero si alguna parte del elemento está visible en la página. Funcionó mejor en mi caso y puede ayudar a alguien más.
function isOnScreen(element) {
var elementOffsetTop = element.offset().top;
var elementHeight = element.height();
var screenScrollTop = $(window).scrollTop();
var screenHeight = $(window).height();
var scrollIsAboveElement = elementOffsetTop + elementHeight - screenScrollTop >= 0;
var elementIsVisibleOnScreen = screenScrollTop + screenHeight - elementOffsetTop >= 0;
return scrollIsAboveElement && elementIsVisibleOnScreen;
}
Esto considera cualquier relleno, borde o margen que tenga el elemento, así como elementos más grandes que la propia ventana gráfica.
function inViewport($ele) {
var lBound = $(window).scrollTop(),
uBound = lBound + $(window).height(),
top = $ele.offset().top,
bottom = top + $ele.outerHeight(true);
return (top > lBound && top < uBound)
|| (bottom > lBound && bottom < uBound)
|| (lBound >= top && lBound <= bottom)
|| (uBound >= top && uBound <= bottom);
}
Para llamarlo usa algo como esto:
var $myElement = $(''#my-element''),
canUserSeeIt = inViewport($myElement);
console.log(canUserSeeIt); // true, if element is visible; false otherwise
Esto debería funcionar:
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
Función de utilidad simple Esto le permitirá llamar a una función de utilidad que acepte el elemento que está buscando y si desea que el elemento esté completamente visible o parcial.
function Utils() {
}
Utils.prototype = {
constructor: Utils,
isElementInView: function (element, fullyInView) {
var pageTop = $(window).scrollTop();
var pageBottom = pageTop + $(window).height();
var elementTop = $(element).offset().top;
var elementBottom = elementTop + $(element).height();
if (fullyInView === true) {
return ((pageTop < elementTop) && (pageBottom > elementBottom));
} else {
return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
}
}
};
var Utils = new Utils();
Uso
var isElementInView = Utils.isElementInView($(''#flyout-left-container''), false);
if (isElementInView) {
console.log(''in view'');
} else {
console.log(''out of view'');
}
Hay un complemento para jQuery llamado inview que agrega un nuevo evento "inview".
Aquí hay algo de código para un complemento de jQuery que no usa eventos:
$.extend($.expr['':''],{
inView: function(a) {
var st = (document.documentElement.scrollTop || document.body.scrollTop),
ot = $(a).offset().top,
wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
return ot > st && ($(a).height() + ot) < (st + wh);
}
});
(function( $ ) {
$.fn.inView = function() {
var st = (document.documentElement.scrollTop || document.body.scrollTop),
ot = $(this).offset().top,
wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
return ot > st && ($(this).height() + ot) < (st + wh);
};
})( jQuery );
Encontré esto en un comentario aquí ( http://remysharp.com/2009/01/26/element-in-view-event-plugin/ ) por un tipo llamado James
He escrito un componente para la tarea, diseñado para manejar grandes cantidades de elementos extremadamente rápido (con una melodía de <10 ms para 1000 elementos en un móvil lento ).
Funciona con cada tipo de contenedor de desplazamiento al que tiene acceso (ventana, elementos HTML, iframe incorporado, ventana secundaria generada) y es muy flexible en lo que detecta ( visibilidad total o parcial , cuadro de borde o cuadro de contenido , zona de tolerancia personalizada, etc ).
Un enorme conjunto de pruebas, en su mayoría autogenerados, garantiza que funcione como se anuncia cross-browser .
Dale una oportunidad si te gusta: jQuery.isInView . De lo contrario, podría encontrar inspiración en el código fuente, por ejemplo, here .
La genial función de Tweeked Scott Dowding para mi requerimiento, se usa para encontrar si el elemento se ha desplazado hacia la pantalla, es decir, es el borde superior.
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}
La mayoría de las respuestas aquí no tienen en cuenta que un elemento también se puede ocultar porque está desplazado fuera de la vista de un div, no solo de toda la página.
Para cubrir esa posibilidad, básicamente tienes que verificar si el elemento está ubicado dentro de los límites de cada uno de sus padres.
Esta solución hace exactamente eso:
function(element, percentX, percentY){
var tolerance = 0.01; //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimals
if(percentX == null){
percentX = 100;
}
if(percentY == null){
percentY = 100;
}
var elementRect = element.getBoundingClientRect();
var parentRects = [];
while(element.parentElement != null){
parentRects.push(element.parentElement.getBoundingClientRect());
element = element.parentElement;
}
var visibleInAllParents = parentRects.every(function(parentRect){
var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
var visiblePercentageX = visiblePixelX / elementRect.width * 100;
var visiblePercentageY = visiblePixelY / elementRect.height * 100;
return visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY;
});
return visibleInAllParents;
};
También le permite especificar a qué porcentaje debe estar visible en cada dirección.
No cubre la posibilidad de que pueda estar oculto debido a otros factores, como display: hidden
.
Esto debería funcionar en todos los navegadores principales, ya que solo usa getBoundingClientRect
. Yo personalmente lo probé en Chrome e Internet Explorer 11.
Modificación simple para div desplazable (contenedor)
var isScrolledIntoView = function(elem, container) {
var containerHeight = $(container).height();
var elemTop = $(elem).position().top;
var elemBottom = elemTop + $(elem).height();
return (elemBottom > 0 && elemTop < containerHeight);
}
NOTA: esto no funciona si el elemento es más grande que el div desplazable.
Necesitaba verificar la visibilidad en los elementos dentro del contenedor DIV desplazable
//p = DIV container scrollable
//e = element
function visible_in_container(p, e) {
var z = p.getBoundingClientRect();
var r = e.getBoundingClientRect();
// Check style visiblilty and off-limits
return e.style.opacity > 0 && e.style.display !== ''none'' &&
e.style.visibility !== ''hidden'' &&
!(r.top > z.bottom || r.bottom < z.top ||
r.left > z.right || r.right < z.left);
}
Prefiero usar jQuery expr
jQuery.extend(jQuery.expr['':''], {
inview: function (elem) {
var t = $(elem);
var offset = t.offset();
var win = $(window);
var winST = win.scrollTop();
var elHeight = t.outerHeight(true);
if ( offset.top > winST - elHeight && offset.top < winST + elHeight + win.height()) {
return true;
}
return false;
}
});
para que puedas usarlo de esta manera
$(".my-elem:inview"); //returns only element that is in view
$(".my-elem").is(":inview"); //check if element is in view
$(".my-elem:inview").length; //check how many elements are in view
Puede agregar fácilmente dicho código dentro de la función de evento de scroll
, etc. para verificarlo cada vez que el usuario desplace la vista.
Puede utilizar el complemento jquery "onScreen" para verificar si el elemento se encuentra en la vista actual cuando se desplaza. El complemento establece el ": onScreen" del selector en verdadero cuando el selector aparece en la pantalla. Este es el enlace para el complemento que puede incluir en su proyecto. " http://benpickles.github.io/onScreen/jquery.onscreen.min.js "
Puedes probar el siguiente ejemplo que funciona para mí.
$(document).scroll(function() {
if($("#div2").is('':onScreen'')) {
console.log("Element appeared on Screen");
//do all your stuffs here when element is visible.
}
else {
console.log("Element not on Screen");
//do all your stuffs here when element is not visible.
}
});
Código HTML:
<div id="div1" style="width: 400px; height: 1000px; padding-top: 20px; position: relative; top: 45px"></div> <br>
<hr /> <br>
<div id="div2" style="width: 400px; height: 200px"></div>
CSS:
#div1 {
background-color: red;
}
#div2 {
background-color: green;
}
Qué tal si
function isInView(elem){
return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;
}
Después de eso, puedes activar lo que quieras una vez que el elemento esté a la vista de esta manera
$(window).scroll(function(){
if (isInView($(''.classOfDivToCheck'')))
//fire whatever you what
dothis();
})
Eso me funciona bien
Se modificó la respuesta aceptada para que el elemento tenga que tener su propiedad de visualización establecida en algo distinto de "ninguno" para que la calidad sea visible.
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
var elemDisplayNotNone = $(elem).css("display") !== "none";
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop) && elemDisplayNotNone);
}
Si desea modificar esto para el elemento de desplazamiento dentro de otro div,
function isScrolledIntoView (elem, divID)
{
var docViewTop = $(''#'' + divID).scrollTop();
var docViewBottom = docViewTop + $(''#'' + divID).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
Tengo un método de este tipo en mi aplicación, pero no usa jQuery:
/* Get the TOP position of a given element. */
function getPositionTop(element){
var offset = 0;
while(element) {
offset += element["offsetTop"];
element = element.offsetParent;
}
return offset;
}
/* Is a given element is visible or not? */
function isElementVisible(eltId) {
var elt = document.getElementById(eltId);
if (!elt) {
// Element not found.
return false;
}
// Get the top and bottom position of the given element.
var posTop = getPositionTop(elt);
var posBottom = posTop + elt.offsetHeight;
// Get the top and bottom position of the *visible* part of the window.
var visibleTop = document.body.scrollTop;
var visibleBottom = visibleTop + document.documentElement.offsetHeight;
return ((posBottom >= visibleTop) && (posTop <= visibleBottom));
}
Edición: este método funciona bien para IE (al menos la versión 6). Lea los comentarios para la compatibilidad con FF.
Un ejemplo basado en esta respuesta para verificar si un elemento es 75% visible (es decir, menos del 25% está fuera de la pantalla).
function isScrolledIntoView(el) {
// check for 75% visible
var percentVisible = 0.75;
var elemTop = el.getBoundingClientRect().top;
var elemBottom = el.getBoundingClientRect().bottom;
var elemHeight = el.getBoundingClientRect().height;
var overhang = elemHeight * (1 - percentVisible);
var isVisible = (elemTop >= -overhang) && (elemBottom <= window.innerHeight + overhang);
return isVisible;
}
Vainilla simple para verificar si el elemento ( el
) es visible en div desplazable ( holder
)
function isElementVisible (el, holder) {
holder = holder || document.body
const { top, bottom, height } = el.getBoundingClientRect()
const holderRect = holder.getBoundingClientRect()
return top <= holderRect.top
? holderRect.top - top <= height
: bottom - holderRect.bottom <= height
},
Uso con jQuery:
var el = $(''tr:last'').get(0);
var holder = $(''table'').get(0);
isVisible = isScrolledIntoView(el, holder);
WebResourcesDepot escribió una secuencia de comandos para cargar mientras se desplaza que usa jQuery hace algún tiempo. Puedes ver su demostración en vivo aquí . La carne de su funcionalidad fue esta:
$(window).scroll(function(){
if ($(window).scrollTop() == $(document).height() - $(window).height()){
lastAddedLiveFunc();
}
});
function lastAddedLiveFunc() {
$(''div#lastPostsLoader'').html(''<img src="images/bigLoader.gif">'');
$.post("default.asp?action=getLastPosts&lastPostID="+$(".wrdLatest:last").attr("id"),
function(data){
if (data != "") {
$(".wrdLatest:last").after(data);
}
$(''div#lastPostsLoader'').empty();
});
};
isScrolledIntoView es una función muy necesaria, así que la probé, funciona para elementos que no son más altos que la ventana gráfica, pero si el elemento es más grande que la ventana gráfica no funciona. Para solucionar este problema fácilmente cambiar la condición
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
a esto:
return (docViewBottom >= elemTop && docViewTop <= elemBottom);
Vea la demostración aquí: http://jsfiddle.net/RRSmQ/
Esta respuesta en vainilla:
function isScrolledIntoView(el) {
var rect = el.getBoundingClientRect();
var elemTop = rect.top;
var elemBottom = rect.bottom;
// Only completely visible elements return true:
var isVisible = (elemTop >= 0) && (elemBottom <= window.innerHeight);
// Partially visible elements return true:
//isVisible = elemTop < window.innerHeight && elemBottom >= 0;
return isVisible;
}
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop(),
docViewBottom = docViewTop + $(window).height(),
elemTop = $(elem).offset().top,
elemBottom = elemTop + $(elem).height();
//Is more than half of the element visible
return ((elemTop + ((elemBottom - elemTop)/2)) >= docViewTop && ((elemTop + ((elemBottom - elemTop)/2)) <= docViewBottom));
}