Ereignis auslösen, wenn Benutzer zu einem bestimmten Element scrollen - mit jQuery


83

Ich habe ein h1, das weit unten auf einer Seite ist.

<h1 id="scroll-to">TRIGGER EVENT WHEN SCROLLED TO.</h1>

und ich möchte eine Warnung auslösen, wenn der Benutzer zum h1 blättert oder es in der Ansicht seines Browsers hat.

$('#scroll-to').scroll(function() {
     alert('you have scrolled to the h1!');
});

Wie mache ich das?

Antworten:


149

Sie können die offsetdes Elements berechnen und diese dann mit dem folgenden scrollWert vergleichen :

$(window).scroll(function() {
   var hT = $('#scroll-to').offset().top,
       hH = $('#scroll-to').outerHeight(),
       wH = $(window).height(),
       wS = $(this).scrollTop();
   if (wS > (hT+hH-wH)){
       console.log('H1 on the view!');
   }
});

Überprüfen Sie diese Demo-Geige


Demo aktualisiert Geige keine Warnung - stattdessen FadeIn () das Element


Der Code wurde aktualisiert, um zu überprüfen, ob sich das Element im Ansichtsfenster befindet oder nicht. Dies funktioniert also unabhängig davon, ob Sie nach oben oder unten scrollen und der if-Anweisung einige Regeln hinzufügen:

   if (wS > (hT+hH-wH) && (hT > wS) && (wS+wH > hT+hH)){
       //Do something
   }

Demo Geige


14
Entprellen Sie dies bitte!
Frambot

1
Gibt es eine Paketbibliothek, die dies als Funktion wie jQuery Waypoint ausführt?
Karl Coelho

1
Danke @DaniP. Cooles Snippet!
Anahit DEV

2
@ClosDesign können Sie verwenden .off(), um das Ereignis jsfiddle.net/n4pdx/543
DaniP

1
@DaniP Ich habe es gerade getan, danke! Und danke für die Antwort, hat mir sehr geholfen :)
Paolo

30

Kombinieren Sie diese Frage mit der besten Antwort der jQuery-Auslöseaktion, wenn ein Benutzer an einem bestimmten Teil der Seite vorbeirollt

var element_position = $('#scroll-to').offset().top;

$(window).on('scroll', function() {
    var y_scroll_pos = window.pageYOffset;
    var scroll_pos_test = element_position;

    if(y_scroll_pos > scroll_pos_test) {
        //do stuff
    }
});

AKTUALISIEREN

Ich habe den Code so verbessert, dass er ausgelöst wird, wenn sich das Element auf halber Höhe des Bildschirms befindet und nicht ganz oben. Der Code wird auch ausgelöst, wenn der Benutzer den unteren Bildschirmrand erreicht und die Funktion noch nicht ausgelöst wurde.

var element_position = $('#scroll-to').offset().top;
var screen_height = $(window).height();
var activation_offset = 0.5;//determines how far up the the page the element needs to be before triggering the function
var activation_point = element_position - (screen_height * activation_offset);
var max_scroll_height = $('body').height() - screen_height - 5;//-5 for a little bit of buffer

//Does something when user scrolls to it OR
//Does it when user has reached the bottom of the page and hasn't triggered the function yet
$(window).on('scroll', function() {
    var y_scroll_pos = window.pageYOffset;

    var element_in_view = y_scroll_pos > activation_point;
    var has_reached_bottom_of_page = max_scroll_height <= y_scroll_pos && !element_in_view;

    if(element_in_view || has_reached_bottom_of_page) {
        //Do something
    }
});

9

Ich denke, Ihre beste Wahl wäre es, eine vorhandene Bibliothek zu nutzen, die genau das tut:

http://imakewebthings.com/waypoints/

Sie können Ihren Elementen Listener hinzufügen, die ausgelöst werden, wenn Ihr Element oben im Ansichtsfenster angezeigt wird:

$('#scroll-to').waypoint(function() {
 alert('you have scrolled to the h1!');
});

Für eine erstaunliche Demo davon im Einsatz:

http://tympanus.net/codrops/2013/07/16/on-scroll-header-effects/


1
Ich habe das schon versucht. Es wird erst ausgelöst, wenn Sie das Element PAST gescrollt haben. Irgendwelche anderen Lösungen?
Karl Coelho

Diese Lösung funktioniert gut, um Empfehlungen abzurufen, und ich habe sie in der Produktion verwendet. Siehe den Blog: liyao13.wordpress.com/2017/05/11/…
Yao Li


4

Sie können dies für alle Geräte verwenden,

$(document).on('scroll', function() {
    if( $(this).scrollTop() >= $('#target_element').position().top ){
        do_something();
    }
});

4

Feuern Sie die Schriftrolle nach einer erfolgreichen Schriftrolle nur einmal ab

Die akzeptierte Antwort funktionierte für mich (90%), aber ich musste sie ein wenig optimieren, um tatsächlich nur einmal zu feuern.

$(window).on('scroll',function() {
            var hT = $('#comment-box-section').offset().top,
                hH = $('#comment-box-section').outerHeight(),
                wH = $(window).height(),
                wS = $(this).scrollTop();

            if (wS > ((hT+hH-wH)-500)){
                console.log('comment box section arrived! eh');
                // After Stuff
                $(window).off('scroll');
                doStuff();
            }

        });

Hinweis : Mit erfolgreichem Bildlauf meine ich, wenn der Benutzer zu meinem Element gescrollt hat oder mit anderen Worten, wenn mein Element angezeigt wird.



2

Dies sollte das sein, was Sie brauchen.

Javascript:

$(window).scroll(function() {
    var hT = $('#circle').offset().top,
        hH = $('#circle').outerHeight(),
        wH = $(window).height(),
        wS = $(this).scrollTop();
    console.log((hT - wH), wS);
    if (wS > (hT + hH - wH)) {
        $('.count').each(function() {
            $(this).prop('Counter', 0).animate({
                Counter: $(this).text()
            }, {
                duration: 900,
                easing: 'swing',
                step: function(now) {
                    $(this).text(Math.ceil(now));
                }
            });
        }); {
            $('.count').removeClass('count').addClass('counted');
        };
    }
});

CSS:

#circle
{
    width: 100px;
    height: 100px;
    background: blue;
    -moz-border-radius: 50px;
    -webkit-border-radius: 50px;
    border-radius: 50px;
    float:left;
    margin:5px;
}
.count, .counted
{
  line-height: 100px;
  color:white;
  margin-left:30px;
  font-size:25px;
}
#talkbubble {
   width: 120px;
   height: 80px;
   background: green;
   position: relative;
   -moz-border-radius:    10px;
   -webkit-border-radius: 10px;
   border-radius:         10px;
   float:left;
   margin:20px;
}
#talkbubble:before {
   content:"";
   position: absolute;
   right: 100%;
   top: 15px;
   width: 0;
   height: 0;
   border-top: 13px solid transparent;
   border-right: 20px solid green;
   border-bottom: 13px solid transparent;
}

HTML:

<div id="talkbubble"><span class="count">145</span></div>
<div style="clear:both"></div>
<div id="talkbubble"><span class="count">145</span></div>
<div style="clear:both"></div>
<div id="circle"><span class="count">1234</span></div>

Überprüfen Sie diese Bootply: http://www.bootply.com/atin_agarwal2/cJBywxX5Qp


2

Intersection Observer kann das Beste sein, IMO, ohne externe Bibliothek macht es einen wirklich guten Job.

const options = {
            root: null,
            threshold: 0.25, // 0 - 1 this work as a trigger. 
            rootMargin: '150px'
        };

        const target = document.querySelector('h1#scroll-to');
        const observer = new IntersectionObserver(
           entries => { // each entry checks if the element is the view or not and if yes trigger the function accordingly
            entries.forEach(() => {
                alert('you have scrolled to the h1!')
            });
        }, options);
        observer.observe(target);

1

Wenn Sie viele Funktionen basierend auf der Bildlaufposition ausführen, wurde Scroll Magic ( http://scrollmagic.io/ ) vollständig für diesen Zweck entwickelt.

Es macht es einfach, JS basierend darauf auszulösen, wann der Benutzer beim Scrollen bestimmte Elemente erreicht. Es lässt sich auch in die GSAP-Animations-Engine ( https://greensock.com/ ) integrieren, die sich hervorragend für Parallax-Scrolling-Websites eignet


1

Nur eine schnelle Änderung der Antwort von DaniP für alle, die sich mit Elementen befassen, die manchmal über die Grenzen des Ansichtsfensters des Geräts hinausgehen können.

Nur eine kleine Bedingung hinzugefügt - Bei Elementen, die größer als das Ansichtsfenster sind, wird das Element angezeigt, sobald die obere Hälfte das Ansichtsfenster vollständig ausgefüllt hat.

function elementInView(el) {
  // The vertical distance between the top of the page and the top of the element.
  var elementOffset = $(el).offset().top;
  // The height of the element, including padding and borders.
  var elementOuterHeight = $(el).outerHeight();
  // Height of the window without margins, padding, borders.
  var windowHeight = $(window).height();
  // The vertical distance between the top of the page and the top of the viewport.
  var scrollOffset = $(this).scrollTop();

  if (elementOuterHeight < windowHeight) {
    // Element is smaller than viewport.
    if (scrollOffset > (elementOffset + elementOuterHeight - windowHeight)) {
      // Element is completely inside viewport, reveal the element!
      return true;
    }
  } else {
    // Element is larger than the viewport, handle visibility differently.
    // Consider it visible as soon as it's top half has filled the viewport.
    if (scrollOffset > elementOffset) {
      // The top of the viewport has touched the top of the element, reveal the element!
      return true;
    }
  }
  return false;
}

Ich würde vorschlagen, weniger kryptische Variablennamen zu verwenden, selbst wenn die akzeptierte Antwort diese verwendet.
Weirdan

0

Ich benutze dabei immer den gleichen Code, also habe ich ein einfaches jquery-Plugin hinzugefügt, das das macht. 480 Bytes lang und schnell. Nur gebundene Elemente werden zur Laufzeit analysiert.

https://www.npmjs.com/package/jquery-on-scrolled-to

Es wird sein $('#scroll-to').onScrolledTo(0, function() { alert('you have scrolled to the h1!'); });

oder verwenden Sie 0,5 anstelle von 0, wenn Sie benachrichtigt werden müssen, wenn die Hälfte des angezeigten h1 angezeigt wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.