Событие триггера, когда пользователь переходит к определенному элементу - с помощью jQuery

88

У меня h1 находится далеко на странице ..

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

и я хочу вызвать предупреждение, когда пользователь прокручивает до h1 или видит его в браузере.

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

Как мне это сделать?

Карл Коэльо
источник

Ответы:

153

Вы можете рассчитать значение offsetэлемента, а затем сравнить его со scrollзначением, например:

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

Проверьте эту демонстрационную скрипку


Обновлен Demo Fiddle без предупреждения - вместо FadeIn () элемент


Обновлен код для проверки, находится ли элемент внутри области просмотра или нет. Таким образом, это работает независимо от того, прокручиваете ли вы вверх или вниз, добавляя некоторые правила в оператор if:

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

Демо скрипка

ДаниП
источник
14
Откажитесь от этого, пожалуйста!
Frambot
1
Есть ли какая-нибудь библиотека пакетов, которая делает это как функцию, например jQuery Waypoint?
Карл Коэльо
1
Спасибо @DaniP. Классный сниппет!
Anahit DEV
2
@ClosDesign можно использовать .off()для отмены
привязки
1
@DaniP Я только что сделал, спасибо! И спасибо за ответ, мне очень помогли :)
Паоло
30

Объединение этого вопроса с лучшим ответом из действия триггера jQuery, когда пользователь прокручивает определенную часть страницы

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

ОБНОВИТЬ

Я улучшил код, так что он срабатывает, когда элемент находится на половине экрана, а не на самом верху. Он также вызовет код, если пользователь коснется нижней части экрана, а функция еще не запущена.

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

Я думаю, что лучше всего было бы использовать существующую библиотеку, которая делает именно это:

http://imakewebthings.com/waypoints/

Вы можете добавить слушателей к своим элементам, которые будут срабатывать, когда ваш элемент попадет в верхнюю часть области просмотра:

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

Для потрясающей демонстрации его использования:

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

Мистер Эпик
источник
1
Я уже пробовал это. Он срабатывает только после того, как вы прокрутите элемент ПРОСТО. Какие-нибудь другие решения?
Карл Коэльо
Это решение хорошо работает для получения рекомендаций, и я использовал его в производстве. См. Блог: liyao13.wordpress.com/2017/05/11/…
Яо Ли
4

Вы можете использовать это для всех устройств,

$(document).on('scroll', function() {
    if( $(this).scrollTop() >= $('#target_element').position().top ){
        do_something();
    }
});
user3444748
источник
4

Огненная прокрутка только один раз после успешной прокрутки

Принятый ответ сработал для меня (90%), но мне пришлось немного его настроить, чтобы на самом деле сработал только один раз.

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

        });

Примечание . Под успешной прокруткой я имею в виду, когда пользователь прокрутил до моего элемента или, другими словами, когда мой элемент находится в поле зрения.

Джунаид
источник
2

Это должно быть то, что вам нужно.

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>

Проверьте эту загрузку: http://www.bootply.com/atin_agarwal2/cJBywxX5Qp

Атин Агарвал
источник
2

Intersection Observer может быть лучшей вещью IMO, без какой-либо внешней библиотеки он действительно хорошо работает.

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

Если вы выполняете много функций в зависимости от позиции прокрутки, Scroll magic ( http://scrollmagic.io/ ) создана полностью для этой цели.

Это упрощает запуск JS в зависимости от того, когда пользователь достигает определенных элементов при прокрутке. Он также интегрируется с движком анимации GSAP ( https://greensock.com/ ), который отлично подходит для сайтов с параллакс-прокруткой.

Дэниел Тонон
источник
1

Просто быстрая модификация ответа DaniP для всех, кто имеет дело с элементами, которые иногда могут выходить за пределы области просмотра устройства.

Добавлено небольшое условие - в случае элементов, которые больше, чем область просмотра, элемент будет показан, когда его верхняя половина полностью заполнит область просмотра.

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;
}
Аллан Сиднейский
источник
Я бы предложил использовать менее загадочные имена переменных, даже если в принятом ответе они используются.
weirdan 01
0

Я использую один и тот же код, делая это все время, поэтому добавил простой плагин jquery, выполняющий это. 480 байт и быстро. Только связанные элементы анализируются во время выполнения.

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

Это будет $('#scroll-to').onScrolledTo(0, function() { alert('you have scrolled to the h1!'); });

или используйте 0,5 вместо 0, если нужно предупредить, когда отображается половина h1.

WowPress.host
источник