Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   В каком направлении и сколько раз был прокручен скролл (https://javascript.ru/forum/events/61272-v-kakom-napravlenii-i-skolko-raz-byl-prokruchen-skroll.html)

webrepa 11.02.2016 13:24

В каком направлении и сколько раз был прокручен скролл
 
Всем привет, собственно сабж. Нужно определить сколько раз и в каком направлении был прокручен скролл (не позиция скролла на странице, а именно сколько раз был прокручен).

Есть классический скрипт:

// Функция для добавления обработчика событий
function addHandler(object, event, handler, useCapture) {
    if (object.addEventListener) {
        object.addEventListener(event, handler, useCapture ? useCapture : false);
    } else if (object.attachEvent) {
        object.attachEvent('on' + event, handler);
    } else alert("Add handler is not supported");
}
// Добавляем обработчики
/* Gecko */
addHandler(window, 'DOMMouseScroll', wheel);
/* Opera */
addHandler(window, 'mousewheel', wheel);
/* IE */
addHandler(document, 'mousewheel', wheel);
// Обработчик события
function wheel(event) {
    var delta; // Направление скролла
    // -1 - скролл вниз
    // 1  - скролл вверх
    event = event || window.event;
    // Opera и IE работают со свойством wheelDelta
    if (event.wheelDelta) {
        delta = event.wheelDelta / 120;
        // В Опере значение wheelDelta такое же, но с противоположным знаком
        if (window.opera) delta = -delta;
    // В реализации Gecko получим свойство detail
    } else if (event.detail) {
        delta = -event.detail / 3;
    }
    // Запрещаем обработку события браузером по умолчанию
    if (event.preventDefault)  event.preventDefault();
    event.returnValue = false;	
   alert(delta);
   return delta;
	
}


Но, тут при каждом движении скролла переменные стираются и переписываются заново. Т.е. можно определить положение, но сколько раз не выходит. Тут идет delta = -1 если вниз и +1 если вверх. Как бы сделать так, чтобы сначала было -1, затем, -2, -3 и т.д. ну или +1, +2, 3 и т.д.

Может быть я конечно и не в том направлении иду. Вообще нужно, чтобы при скроллинге 1 элемент (на всю высоту экрана) заменялся другим и т.д., а сам скролл на сайте был бы отключен.

Спасибо.

DynkanMaclaud 11.02.2016 13:29

webrepa,
почему вы не поставите счетчик на событие mousewheel??? То есть если дельта больше 120 то в переменная i +=1; else q+=1; соответственно i,q - глобальные переменные для этой функции по умолчанию равные 0

webrepa 11.02.2016 13:33

Буду рад если подскажите как :)

webrepa 11.02.2016 13:37

Цитата:

Сообщение от DynkanMaclaud (Сообщение 407262)
webrepa,
почему вы не поставите счетчик на событие mousewheel??? То есть если дельта больше 120 то в переменная i +=1; else q+=1; соответственно i,q - глобальные переменные для этой функции по умолчанию равные 0

Не совсем понимаю как это сделать - можете показать? Спасибо.

Dilettante_Pro 11.02.2016 13:43

webrepa,
Цитата:

Сообщение от webrepa
Как бы сделать так, чтобы сначала было -1, затем, -2, -3 и т.д. ну или +1, +2, 3 и т.д.

Пропишите глобальную переменную, напр.
var countDelta;

а в конце функции
countDelta += delta;

рони 11.02.2016 13:44

webrepa,
строка 16 var q = 0;
строка 34 q += delta;

webrepa 11.02.2016 14:13

И всего-то. Спасибо всем огромное. Не пойму почему у меня так не получалось. Раз 100 делал. Видимо натупил в области видимости и объявлял переменные внутри функций. Спасибо еще раз.

webrepa 11.02.2016 15:28

Возникла новая ситуация. Т.к. я использую эту функцию, чтобы мотать "блоки", то выходит, что если пользователь со всей дури мотанул скролл, то значение увеличивается\уменьшается не на 1. Как бы этого избежать? Буду признателен ответу :)

рони 11.02.2016 15:33

webrepa,
копать debounce

webrepa 11.02.2016 17:36

Что-то так ничего и не выходит. Сейчас скрипт такой:

<script>
	// Функция для добавления обработчика событий
function addHandler(object, event, handler, useCapture) {
    if (object.addEventListener) {
        object.addEventListener(event, handler, useCapture ? useCapture : false);
    } else if (object.attachEvent) {
        object.attachEvent('on' + event, handler);
    } else alert("Add handler is not supported");
}
// Добавляем обработчики
/* Gecko */
addHandler(window, 'DOMMouseScroll', wheel);
/* Opera */
addHandler(window, 'mousewheel', wheel);
/* IE */
addHandler(document, 'mousewheel', wheel);
// Обработчик события
var q = 0;
function wheel(event) {
    var delta; // Направление скролла
    // -1 - скролл вниз
    // 1  - скролл вверх
    event = event || window.event;
    // Opera и IE работают со свойством wheelDelta
    if (event.wheelDelta) {
        delta = event.wheelDelta / 120;
        // В Опере значение wheelDelta такое же, но с противоположным знаком
        if (window.opera) delta = -delta;
    // В реализации Gecko получим свойство detail
    } else if (event.detail) {
        delta = -event.detail / 3;
    }
	// Запрещаем обработку события браузером по умолчанию
    if (event.preventDefault)  event.preventDefault();
    event.returnValue = false;	
	q += delta;
	document.getElementById('div1').innerHTML = q;		
	return delta;
	
}
	</script>

в div1 вывожу результат, чтобы проверять, т.к. через alert стопорит после первого изменения.
Не пойму как debounce сюда впихнуть.

рони 11.02.2016 18:09

webrepa,
начало скрола if(flag)temp = q , flag = false , timer = 100ms
через 100ms принять решение if(q > temp) крутим до ближайшего следущего иначе до ближайшего предыдущего

webrepa 11.02.2016 18:18

А можете вновь немного подробнее, пожалуйста.

рони 11.02.2016 18:24

webrepa,
готовое решение от devote
http://javascript.ru/forum/dom-windo...tml#post312682

webrepa 12.02.2016 11:29

Если не тяжело, подскажите по флагу, пожалуйста. Мне бы очень хотелось все понять и применить. Если не сложно укажите как это написать и где, а я потом буду анализировать и додумывать что, как и почему.
Спасибо.

рони 12.02.2016 12:03

webrepa, примерно так, только вместо window.pageYOffset будет сумма delta в q
<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
    div, body, html{
      height: 100%;
    }
    p{
       position: fixed;
    }

  </style>

  <script>



 window.addEventListener('DOMContentLoaded', function() {
   var temp = 0 , flag = true , timer;
   window.addEventListener('scroll', function () {
      if(flag) {temp = window.pageYOffset;flag = false; document.querySelector('p').innerHTML = 'ждём окончания скрола'}
      window.clearTimeout(timer);
      window.setTimeout(fn,1000)
   });
   function fn()
   {  flag = true;
      document.querySelector('p').innerHTML = (window.pageYOffset > temp ? "крутим вниз" : "крутим вверх")
   }

     });
  </script>
</head>

<body>
<p></p>

<div id="dizzy">Dizzy
  <!-- panel content -->
</div>
<div id="ninja">Ninja
  <!-- panel content -->
</div>
<div id="missy">Missy
  <!-- panel content -->
</div>
</body>

</html>

webrepa 12.02.2016 13:05

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

рони 12.02.2016 14:10

webrepa,
решайте вопрос по своему алгоритму, главное его придумать и проверить, на чужом не зацикливайтесь.

webrepa 12.02.2016 14:14

Придумал не самое изящное решение наверное, но всю функцию обернул в if, где она выполняется только если flag == true. Перед функцией поставил flag в true, а перед завершением flag в false. Затем setTimeout('flag = true', 1000);
Получилось что надо вроде бы. Срабатывает 1 раз в секунду. Хотя наверное есть и поизящнее решения.
Но Вам отдельное спасибо за помощь.

рони 12.02.2016 14:22

webrepa,
хороший debounce так и позволяет либо запустить функцию только в самом начале прокрутки один раз или по окончании скролинга тоже 1 раз (как вам нужно, настраивается в опциях)

webrepa 12.02.2016 14:45

Да, Вы правы. Все верно :)


Часовой пояс GMT +3, время: 09:17.