2010-09-27 18 views
19

Czy jest jakaś technika lub zestaw technik, które można wykorzystać do implementacji tego, co w efekcie byłoby "wydarzeniem" OnVisible w JavaScript?Jak zaimplementować zdarzenie "onVisible" w JavaScript?

Chciałbym, aby mój JavaScript wykrył, kiedy element na stronie internetowej, taki jak akapit tekstu, lub obraz, staje się widoczny w oknie przeglądarki, gdy użytkownik przewija stronę w dół. Chciałbym również, aby odpowiednie "wydarzenie" na NotVisible uruchamiało się, gdy element, który był kiedyś widoczny w oknie przeglądarki, nie będzie już widoczny.

Jeśli nie można go łatwo zaimplementować w JavaScript, czy są jakieś zdarzenia związane z przeglądarką, które mogą zapewnić tę samą funkcjonalność?

+0

może to pomóc http://stackoverflow.com/questions/399867/custom-events-in-jquery –

+2

patrz http://stackoverflow.com/questions/487073/jquery-check-if-element- is-visible-after-scroling – edbond

Odpowiedz

5

Konieczne byłoby skonfigurowanie detektora zdarzeń dla zdarzenia onscroll dokumentu lub okna. Następnie należy zmierzyć aktualnie widoczny obszar, dodając pozycję ClientHeight do scrollTop, a następnie sprawdzić, czy wybrany element znajduje się w tym obszarze. Coś w tym stylu:

myElem=document.getElementById('some_id'); 
scrollOffset=document.getElementsByTagName('html')[0].scrollTop; 
visibleHeight=document.getElementsByTagName('html')[0].clientHeight; 
if(myElem.offsetTop>=scrollOffset && myElem.offsetTop<=scrollOffset+visibleHeight){ 
    // element is in visible area 
} 

Jeśli tak jest, to ustawiamy flagę gdzieś w kodzie.

Prawdopodobnie jednak wystąpią niezgodności przeglądarki. Lepiej skorzystaj z biblioteki.

+0

Jak sprawdzić, czy wybrany element znajduje się w tym obszarze? – RobertG

+0

Dodałem przykład. – DanMan

8

musiałem spróbować sam, i to, co wymyśliłem:

<!DOCTYPE html> 
<html> 
<head> 
<script> 

var EventListener = function(element, callback) { 
    this._el = element; 
    this._cb = callback; 
    this._at = false; 
    this._hasBeenVisible = false; 
    this._hasBeenInvisible = true; 
    var _me = this; 

    window.onscroll = function() { 
     for (q in EventListener.queue.onvisible) { 
      EventListener.queue.onvisible[q].call(); 
     } 
     for (q in EventListener.queue.oninvisible) { 
      EventListener.queue.oninvisible[q].call(); 
     } 
    }; 

    return { 
     onvisible: function() { 
      EventListener.queue.onvisible.push(function() { 
       if (!_me._at && _me._hasBeenInvisible && (window.pageYOffset + window.innerHeight) > _me._el.offsetTop && window.pageYOffset < (_me._el.offsetTop + _me._el.scrollHeight)) { 
        _me._cb.call(); 
        _me._at = true; 
        _me._hasBeenVisible = true; 
       } 
      }); 
      EventListener.queue.oninvisible.push(function() { 
       if (_me._hasBeenVisible && ((window.pageYOffset + window.innerHeight) < _me._el.offsetTop || window.pageYOffset > (_me._el.offsetTop + _me._el.scrollHeight))) { 
        _me._hasBeenInvisible = true; 
        _me._hasBeenVisible = false; 
        _me._at = false; 
       } 
      }); 
     }, 
     oninvisible: function() { 
      EventListener.queue.oninvisible.push(function() { 
       if (!_me._at && _me._hasBeenVisible && ((window.pageYOffset + window.innerHeight) < _me._el.offsetTop || window.pageYOffset > (_me._el.offsetTop + _me._el.scrollHeight))) { 
        _me._cb.call(); 
        _me._at = true; 
        _me._hasBeenInvisible = true; 
       } 
      }); 
      EventListener.queue.onvisible.push(function() { 
       if (_me._hasBeenInvisible && (window.pageYOffset + window.innerHeight) > _me._el.offsetTop && window.pageYOffset < (_me._el.offsetTop + _me._el.scrollHeight)) { 
        _me._hasBeenVisible = true; 
        _me._hasBeenInvisible = false; 
        _me._at = false; 
       } 
      }); 
     } 
    }; 
} 
EventListener.queue = { 
    onvisible: [], 
    oninvisible: [] 
}; 

function addListener(element, event, fn) { 
    if (typeof element == 'string') 
     element = document.getElementById(element); 

    var listener = new EventListener(element, fn); 

    if (listener['on' + event.toLowerCase()]) 
     return listener['on' + event.toLowerCase()].call(); 
} 

window.onload = function() { 
    addListener('event-element', 'visible', function() { 
     alert("Element One Visible!"); 
    }); 
    addListener('event-element', 'invisible', function() { 
     alert("Element One Invisible!"); 
    }); 
    addListener('event2-element', 'visible', function() { 
     alert("Element Two Visible!"); 
    }); 
    addListener('event2-element', 'invisible', function() { 
     alert("Element Two Invisible"); 
    }); 
} 

</script> 
</head> 
<body> 

<h1>Hey!</h1> 

<div style="height: 1500px;"> 
Please scroll down some pixels. 
</div> 

<p id="event-element"> 
    This element should cast an event 'onvisible' and 'oninvisible'. 
</p> 

<div style="height: 1000px;"> 

</div> 

<p id="event2-element"> 
    Another one! 
</p> 


</body> 
</html> 

Testowane:

  • Firefox 3.6 (działa)
  • Chrome 6.0.472 (prac)
  • Opera 10.62 (prace)
  • Safari 4 (działa w bardzo buggy i irytujący sposób, nie nas e wyskakujące okna czy spróbować tutaj!)

(The code is also available on PasteBin)

Powyższy kod nie jest zoptymalizowany w jakikolwiek sposób, po prostu zacząłem pisać i skończyła się, gdy pracował. Najlepiej byłoby, gdybyś użył tylko jednej kolejki, zredagował jakiś kod i uczynił go bardziej ogólnym. Pod warunkiem, że jest.

+0

+1 niezła dokładna odpowiedź. – LarsH

+1

Dobra odpowiedź. Nie uwzględnia to jednak atrybutu wyświetlania! Należy przejść przez element parentNode do góry i sprawdzić, czy wszystkie jego atrybuty wyświetlania są widoczne. Bardzo przydatne przy ładowaniu zawartości na żądanie. –

+0

Tutaj jest na jsbin: http://jsbin.com/ewoqey/1/edit –

4

Jeden z answers w question połączony powyżej przez @edbond podaje wskaźnik do jQuery appear plugin. Ta wtyczka umożliwia dołączanie wywołań zwrotnych od appear i disappear do elementu, który jest wywoływany jako element przewijany do i z widoku, co brzmi dokładnie tak, jak tego szukasz.

Powiązane problemy