Задать вопрос
yaleksandr89
@yaleksandr89
PHP developer

Как правильно реализовать «продвинутую» прокрутку страницы?

Здравствуйте.

Никак не могу разобраться со следубщей ситуацией.

Если в теории, если элемент на странице, появление которого нужно отследить (событие scroll) - это сделано. Загвоздка заключается в том, что когда срабатывает событие остлеживающее появление элемента на в области видимости, запускается другое (аналогичное событие scroll), которое в свою очередь отвечает за проверку, в какую строну производиться прокрутка страницы (вверх низ). И я никак не могу реализовать, что бы после того, как элемент выйдет за область видимости, с обработчика события снялась только функция, которая отслеживает в какую сторону производиться прокрутка

Код: функция, которая отслеживает появился\скрылся ли элемент из области видимости:
var self = $(this),
    blockShow = null,
    offsetTop = settings.offsetTop,
    offsetBottom = settings.offsetBottom;

/**
 * Функция определяет, находиться элемент в области видимости или нет.
 * Дополнительно (пользовательские отспупы):
 * scrollTop - отсутп сверх
 * offsetBottom - отступ снизу
 *
 * @returns {boolean|boolean}
 */
function is_shown() {
    /**
     * @var wt - windows scrollTop
     * @var wh - windows height
     * @var et - target element
     * @var eh - element height
     */
    var wt = parseFloat($(window).scrollTop().toFixed()),
        wh = parseFloat($(window).height().toFixed()),
        et = parseFloat(self.offset().top.toFixed()),
        eh = parseFloat(self.outerHeight().toFixed());
    return (wt + wh) - offsetTop >= et && (wt + wh - eh * 2) <= et + (wh - eh) - offsetBottom;
}


Функция, которая определяет в какую сторону производиться прокрутка (когда элемент находиться в области видимости):
function scrollTracking() {
    var lastScrollTop = 0;
    $(document).on('scroll', function () {
        var currentScrollTop = $(this).scrollTop();
        if (currentScrollTop > lastScrollTop) {
            console.log('Прокрутка вниз');
        } else {
            console.log('Прокрутка вверх');
        }
        lastScrollTop = currentScrollTop;
    });
}


Объединяю написанные функции:
return $(document).on('scroll', function () {
    if (is_shown()) {
        if (blockShow === null || blockShow === false) {
            console.log('Блок ' + self.attr('class') + ' ПОЯВИЛСЯ');
            scrollTracking();
        }
        blockShow = true;
    } else {
        if (blockShow === null || blockShow === true) {
            console.log('Блок ' + self.attr('class') + ' СКРЫТ');
        }
        blockShow = false;
        //$(document).off('scroll', scrollTracking());
    }
})


На деле получается следующее, событие: когда элемент появляется в области видимости, срабатывает функция, которая определеяет в какую сторону идет прокрутка. Но когда элемент выходит из области видимости функция scrollTracking(); не перестает работать (а должна).

Я специально оставил закоментированную строку $(document).off('scroll', scrollTracking());, так как это первое, что пришло в голову - когда элемент скрывает из области видимости - убираю функцию scrollTracking() и радуюсь жизни.

Но пофакту, убирается не только функция, которая отслеживает в какую сторону производиться прокрутка, но и функция, которая определяет - находиться ли элемент в области видимости или нет. Второй день мытарств - не привел ни к чему :( поэтому прощуподсказать.

Буду крайне признателен
  • Вопрос задан
  • 101 просмотр
Подписаться 1 Средний 5 комментариев
Решения вопроса 1
yaleksandr89
@yaleksandr89 Автор вопроса
PHP developer
Все такие полезно иногда излогать свои мысли на публику, после написания вопроса в очередной раз полез читать про события в js. И нашел решение, если коротко - вешая на событие несколько действий пользуйтесь пространствами имен.

Фактически мне нужно было разделить просто прокрутку страницы и прокрутку страницы, когда нужный блок появляется в области видимости. Решение:
scrollTracking()

Было:
function scrollTracking() {
    var lastScrollTop = 0;
    $(document).on('scroll', function () {
        var currentScrollTop = $(this).scrollTop();
        if (currentScrollTop > lastScrollTop) {
            console.log('Прокрутка вниз');
        } else {
            console.log('Прокрутка вверх');
        }
        lastScrollTop = currentScrollTop;
    });
}


Стало:
function scrollTracking() {
    var lastScrollTop = 0;
    $(document).on('scroll.scrollTracking', function () {
        var currentScrollTop = $(this).scrollTop();
        if (currentScrollTop > lastScrollTop) {
            console.log('Прокрутка вниз');
        } else {
            console.log('Прокрутка вверх');
        }
        lastScrollTop = currentScrollTop;
    });
}



И общая прокрутка:
return $(document).on('scroll.isShow', function () {
                if (is_shown()) {
                    if (blockShow === null || blockShow === false) {
                        console.log('Блок ' + self.attr('class') + ' ПОЯВИЛСЯ');
                        scrollTracking();
                    }
                    blockShow = true;
                } else {
                    $(document).off('scroll.scrollTracking',scrollTracking());
                    if (blockShow === null || blockShow === true) {
                        console.log('Блок ' + self.attr('class') + ' СКРЫТ');
                    }
                    blockShow = false;
                }
            })


Используя пространство имен, я безболезненно смог удалить обработчик:
$(document).off('scroll.scrollTracking',scrollTracking());
Оставив, общий, отвечающий за определение - находиться ли элемент в области видимости или нет
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы