Sự kiện kích hoạt khi người dùng cuộn đến phần tử cụ thể - với jQuery


83

Tôi có một h1 ở xa một trang ..

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

và tôi muốn kích hoạt cảnh báo khi người dùng cuộn đến h1 hoặc có nó trong chế độ xem của trình duyệt.

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

Làm thế nào để tôi làm điều này?

Câu trả lời:


149

Bạn có thể tính toán offsetphần tử và sau đó so sánh với scrollgiá trị như:

$(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!');
   }
});

Kiểm tra Fiddle Demo này


Cập nhật Demo Fiddle không có cảnh báo - thay vào đó là phần tử FadeIn ()


Đã cập nhật mã để kiểm tra xem phần tử có bên trong khung nhìn hay không. Do đó, điều này hoạt động cho dù bạn đang cuộn lên hoặc xuống để thêm một số quy tắc vào câu lệnh if:

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

Demo Fiddle


14
Debounce này xin vui lòng!
Frambot

1
Có thư viện gói nào thực hiện điều này như một hàm như jQuery Waypoint không?
Karl Coelho

1
Cảm ơn @DaniP. Đoạn mã thú vị!
Anahit DEV

2
@ClosDesign bạn có thể sử dụng .off()để hủy liên kết sự kiện jsfiddle.net/n4pdx/543
DaniP

1
@DaniP Tôi vừa làm, cảm ơn! Và cảm ơn vì câu trả lời, đã giúp tôi rất nhiều :)
Paolo

30

Kết hợp câu hỏi này với câu trả lời hay nhất từ hành động kích hoạt jQuery khi người dùng cuộn qua một phần nhất định của trang

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
    }
});

CẬP NHẬT

Tôi đã cải thiện mã để nó sẽ kích hoạt khi phần tử ở nửa màn hình thay vì ở trên cùng. Nó cũng sẽ kích hoạt mã nếu người dùng chạm vào cuối màn hình và chức năng vẫn chưa kích hoạt.

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

Tôi nghĩ đặt cược tốt nhất của bạn sẽ là tận dụng một thư viện hiện có thực hiện điều đó:

http://imakewebthings.com/waypoints/

Bạn có thể thêm trình nghe vào các phần tử của mình sẽ tắt khi phần tử của bạn chạm vào đầu khung nhìn:

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

Để có một bản demo tuyệt vời về nó đang được sử dụng:

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


1
Tôi đã thử cái này rồi. Nó chỉ kích hoạt khi bạn đã cuộn phần tử PAST. Bất kỳ giải pháp nào khác?
Karl Coelho

Giải pháp này hoạt động tốt để tìm nạp các đề xuất và tôi đã sử dụng nó trong sản xuất. Tham khảo blog: liyao13.wordpress.com/2017/05/11/…
Yao Li


4

Bạn có thể sử dụng điều này cho tất cả các thiết bị,

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

4

Kích hoạt cuộn chỉ một lần sau khi cuộn thành công

Câu trả lời được chấp nhận phù hợp với tôi (90%) nhưng tôi phải điều chỉnh nó một chút để thực sự chỉ kích hoạt một lần.

$(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();
            }

        });

Lưu ý : Khi cuộn thành công, ý tôi là khi người dùng đã cuộn đến phần tử của tôi hay nói cách khác là khi phần tử của tôi đang ở chế độ xem.



2

Đây sẽ là những gì bạn cần.

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>

Kiểm tra bootply này: http://www.bootply.com/atin_agarwal2/cJBywxX5Qp


2

Intersection Observer có thể là thứ tốt nhất IMO, mà không cần bất kỳ thư viện bên ngoài nào, nó hoạt động rất tốt.

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

Nếu bạn đang thực hiện nhiều chức năng dựa trên vị trí cuộn, Scroll magic ( http://scrollmagic.io/ ) được xây dựng hoàn toàn cho mục đích này.

Nó giúp dễ dàng kích hoạt JS dựa trên thời điểm người dùng tiếp cận các phần tử nhất định khi cuộn. Nó cũng tích hợp với công cụ hoạt ảnh GSAP ( https://greensock.com/ ), rất tốt cho các trang web cuộn thị sai


1

Chỉ là một sửa đổi nhanh chóng cho câu trả lời của DaniP, dành cho bất kỳ ai xử lý các yếu tố đôi khi có thể vượt ra ngoài giới hạn của khung nhìn của thiết bị.

Chỉ thêm một điều kiện nhỏ - Trong trường hợp các phần tử lớn hơn khung nhìn, phần tử sẽ được hiển thị khi nửa trên của nó đã lấp đầy hoàn toàn khung nhìn.

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;
}

Tôi khuyên bạn nên sử dụng các tên biến ít khó hiểu hơn, ngay cả khi câu trả lời được chấp nhận sử dụng chúng.
kỳ lạ

0

Tôi sử dụng cùng một mã để làm điều đó mọi lúc, vì vậy đã thêm một plugin jquery đơn giản để làm điều đó. Dài 480 byte và nhanh chóng. Chỉ các phần tử bị ràng buộc được phân tích trong thời gian chạy.

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

Nó sẽ là $('#scroll-to').onScrolledTo(0, function() { alert('you have scrolled to the h1!'); });

hoặc sử dụng 0,5 thay vì 0 nếu cần cảnh báo khi một nửa h1 hiển thị.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.