滑动时防止touchstart

DA.*_*DA. 40 javascript jquery scroll touch touch-event

我在移动设备上有一个可滚动的列表.他们希望人们能够通过滑动滚动列表,并通过点击选择一行.

抓住了两者.如果您实际滚动列表,我不希望选择一行.这是我发现的:

滚动时不触发:

  • 点击
  • 鼠标松开

滚动时是否触发:

  • 鼠标按下
  • touchstart
  • touchend

简单的解决方案就是坚持点击事件.但我们发现,在某些黑莓设备上,touchstart之间存在非常明显的延迟,然后触发点击或鼠标.这种延迟足以使其在这些设备上无法使用.

所以这给我们留下了其他选择.但是,使用这些选项,您可以滚动列表而不触发您触摸的行以启动滚动.

解决此问题的最佳做法是什么?

Lev*_*ker 47

var touchmoved;
$('button').on('touchend', function(e){
    if(touchmoved != true){
        // button click action
    }
}).on('touchmove', function(e){
    touchmoved = true;
}).on('touchstart', function(){
    touchmoved = false;
});
Run Code Online (Sandbox Code Playgroud)

  • 这样做以某种方式取消了我的滚动动作。 (2认同)

Net*_*dia 23

你基本上想要做的是检测什么是滑动以及什么是点击.

我们可能会设置一些条件:

  1. 滑动是指您触摸点p1,然后将手指移动到指向p2同时仍然将手指放在屏幕上,然后松开.
  2. 点击是指您点击开始点击并结束点击同一元素.

因此,如果您存储您所在位置的坐标touchStart,则可以测量其中的差异touchEnd.如果更改足够大,请将其视为滑动,否则,请将其视为单击.

此外,如果你想要做得非常整洁,你还可以在一个时间内用手指检测到你正在"悬停"的元素touchMove,如果你还没有在你开始点击的元素上,你可以运行一个clickCancel去除高光等的方法

// grab an element which you can click just as an example
var clickable = document.getElementById("clickableItem"),
// set up some variables that we need for later
currentElement,
clickedElement;

// set up touchStart event handler
var onTouchStart = function(e) {
    // store which element we're currently clicking on
    clickedElement = this;
    // listen to when the user moves finger
    this.addEventListener("touchMove" onTouchMove);
    // add listener to when touch end occurs
    this.addEventListener("touchEnd", onTouchEnd);
};
// when the user swipes, update element positions to swipe
var onTouchMove = function(e) {
    // ... do your scrolling here

    // store current element
    currentElement = document.elementFromPoint(x, y);
    // if the current element is no longer the same as we clicked from the beginning, remove highlight
    if(clickedElement !== currentElement) {
        removeHighlight(clickedElement);
    }
};
// this is what is executed when the user stops the movement
var onTouchEnd = function(e) {
    if(clickedElement === currentElement) {
        removeHighlight(clickedElement);
        // .... execute click action
    }

    // clean up event listeners
    this.removeEventListener("touchMove" onTouchMove);
    this.removeEventListener("touchEnd", onTouchEnd);
};
function addHighlight(element) {
    element.className = "highlighted";
}
function removeHighlight(element) {
    element.className = "";
}
clickable.addEventListener("touchStart", onTouchStart);
Run Code Online (Sandbox Code Playgroud)

然后,你将不得不侦听器添加到您滚动的元素还,但你不必担心,如果手指移动其间发生了什么touchStarttouchEnd.

var scrollable = document.getElementById("scrollableItem");

// set up touchStart event handler
var onTouchStartScrollable = function(e) {
    // listen to when the user moves finger
    this.addEventListener("touchMove" onTouchMoveScrollable);
    // add listener to when touch end occurs
    this.addEventListener("touchEnd", onTouchEndScrollable);
};
// when the user swipes, update element positions to swipe
var onTouchMoveScrollable = function(e) {
    // ... do your scrolling here
};
// this is what is executed when the user stops the movement
var onTouchEndScrollable = function(e) {
    // clean up event listeners
    this.removeEventListener("touchMove" onTouchMoveScrollable);
    this.removeEventListener("touchEnd", onTouchEndScrollable);
};
scrollable.addEventListener("touchStart", onTouchStartScrollable);
Run Code Online (Sandbox Code Playgroud)

// Simon A.


DA.*_*DA. 17

这是我最终提出的允许通过滑动滚动项目列表,但每个项目通过点击可以"触发".此外,您仍然可以使用键盘(使用onclick).

我认为这类似于Netlight_Digital_Media的回答.我需要多研究一下.

$(document)
// log the position of the touchstart interaction
.bind('touchstart', function(e){ 
  touchStartPos = $(window).scrollTop();
})
// log the position of the touchend interaction
.bind('touchend', function(e){
  // calculate how far the page has moved between
  // touchstart and end. 
  var distance = touchStartPos - $(window).scrollTop();

  var $clickableItem; // the item I want to be clickable if it's NOT a swipe

  // adding this class for devices that
  // will trigger a click event after
  // the touchend event finishes. This 
  // tells the click event that we've 
  // already done things so don't repeat

  $clickableItem.addClass("touched");      

  if (distance > 20 || distance < -20){
        // the distance was more than 20px
        // so we're assuming they intended
        // to swipe to scroll the list and
        // not selecting a row. 
    } else {
        // we'll assume it was a tap 
        whateverFunctionYouWantToTriggerOnTapOrClick()
    }
});


$($clickableItem).live('click',function(e){
 // for any non-touch device, we need 
 // to still apply a click event
 // but we'll first check to see
 // if there was a previous touch
 // event by checking for the class
 // that was left by the touch event.
if ($(this).hasClass("touched")){
  // this item's event was already triggered via touch
  // so we won't call the function and reset this for
  // the next touch by removing the class
  $(this).removeClass("touched");
} else {
  // there wasn't a touch event. We're
  // instead using a mouse or keyboard
  whateverFunctionYouWantToTriggerOnTapOrClick()
}
});
Run Code Online (Sandbox Code Playgroud)


jos*_*ard 6

引自DA:

这是一个有效的例子:

var touch_pos;
$(document).on('touchstart', '.action-feature', function(e) {
  e.preventDefault();
  touch_pos = $(window).scrollTop();
}).on('click touchend', '.action-feature', function(e) {
  e.preventDefault();
  if(e.type=='touchend' && (Math.abs(touch_pos-$(window).scrollTop())>3)) return;
  alert("only accessed when it's a click or not a swipe");
});
Run Code Online (Sandbox Code Playgroud)