Определить, остановил ли элемент прокрутку импульса?

Можно ли определить, прекратил ли прокрутку элемент в Mobile Safari через Javascript?

У меня есть элемент с прокруткой импульса с помощью -webkit-overflow-scrolling:touch, и мне нужно определить, прекратил ли прокрутку элемент, в том числе после того, как импульс повлиял на прокрутку.

Это возможно? Использование события onscroll не работает должным образом в моем приложении.


person Charlie    schedule 11.12.2012    source источник


Ответы (3)


Вы можете рассчитать скорость прокрутки и попытаться выяснить, произойдет ли прокрутка импульса на основе некоторого порогового значения. Я провел некоторые тесты, и около 0,25 пикселей/мс кажется хорошим значением.

Примечание. Иногда прокрутка импульса происходит и при более низких скоростях. Самая низкая скорость, вызывающая прокрутку импульса, которую я зафиксировал, составляла 0,13 (с очень коротким дельта-временем), поэтому, если вам нужно 100% идеальное решение, продолжайте искать.

Пример кода также обнаруживает и устраняет чрезмерную прокрутку.

Использование JQuery;

var scrollWrapper = $('#myWrapper');
var starTime, startScroll, waitForScrollEvent;
scrollWrapper.bind('touchstart', function() {
   waitForScrollEvent = false;
});

scrollWrapper.bind('touchmove', function() { 
  startTime = new Date().getTime(); startScroll = scrollWrapper.scrollTop();
});

scrollWrapper.bind('touchend', function() {
  var deltaTime = new Date().getTime() - startTime;
  var deltaScroll = Math.abs(startScroll - scrollWrapper.scrollTop());
  if (deltaScroll/deltaTime>0.25 
        || scrollWrapper.scrollTop()<0 
        || scrollWrapper.scrollTop()>scrollWrapper.height()) {
    // will cause momentum scroll, wait for 'scroll' event
    waitForScrollEvent = true;
  }
  else {
    onScrollCompleted(); // assume no momentum scroll was initiated
  }
  startTime = 0;
});

scrollWrapper.bind('scroll', function() {
  if (waitForScrollEvent) {
    onScrollCompleted();
  }
});
person dagge    schedule 01.04.2014
comment
Это фантастика! Я изо всех сил пытался сделать внутренний div прокручиваемым, и, включив импульс, вся логика привязки, которая у меня была, вышла из окна. Вам не хватает пары запятых, а переменная-оболочка не определена. В противном случае это здорово! - person Chris; 16.05.2014
comment
Рад, что вы нашли это полезным. Спасибо, что указали на ошибки. - person dagge; 17.05.2014
comment
очень хорошо. сделать демо для него. другим может быть полезно быстро проверить результат - person iraj jelodari; 07.11.2017
comment
Я не понимаю, вы просто слушаете первое событие прокрутки. Когда происходит прокрутка импульса, она продолжает генерировать события прокрутки до конца. Правильный ответ ниже. - person waterplea; 08.02.2019
comment
Это было давно. Я считаю, что суть проблемы заключалась в том, что в Mobile Safari события прокрутки не генерировались во время прокрутки по импульсу. Именно это пытался решить приведенный выше код. Возможно, с тех пор это изменилось. - person dagge; 08.02.2019

В моем случае это сработало отлично:

var timer;
$(scrollWrapper).on('scroll',function(e){
    if(timer){
        clearTimeout(timer);
    }
    timer = setTimeout(function(){
       $(this).trigger('scrollFinished');
    }, 55)
})



 $(scrollWrapper).on('scrollFinished',function(){
         // will be called when momentum scroll is finished
   })

Публиковать событие «scrollfinished», когда прокрутка остановлена.

person rishabh dev    schedule 25.01.2016
comment
Интересная техника, для некоторых конкретных случаев использования она может быть даже лучше, чем принятый ответ (как это было в моем случае). +1 - person Teodor Sandu; 22.03.2016
comment
Отличное простое решение, хотя мне пришлось настроить длину timeOut на большее число. - person Arjan; 06.01.2018

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

isScrolling() {
  var scrollStart = <element>.scrollTop;
  setTimeout(function() {
    var scrollPos = <element>.scrollTop;
    if (scrollStart !== scrollPos) {
      this.isScrolling()
    } else {
      // Scrolling has stopped
    }
  }, 100)
}
person tjaydk    schedule 19.09.2019