Javascript 刷卡时防止touchstart

Javascript 刷卡时防止touchstart,javascript,jquery,scroll,touch,touch-event,Javascript,Jquery,Scroll,Touch,Touch Event,我在移动设备上有一个可滚动列表。他们希望人们能够通过滑动滚动列表,也可以通过点击选择一行 关键是把两者结合起来。如果您确实在滚动列表,我不希望选择一行。以下是我的发现: 滚动时不触发: 点击 鼠标 滚动时是否触发: 穆斯敦 触控启动 接触端 简单的解决方案就是坚持点击事件。但我们发现,在某些黑莓设备上,touchstart和它触发click或mouseup之间有一个非常明显的延迟。此延迟严重到足以使其在这些设备上无法使用 因此,我们还有其他选择。但是,使用这些选项,您可以滚动列表,而无需

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

关键是把两者结合起来。如果您确实在滚动列表,我不希望选择一行。以下是我的发现:

滚动时不触发:

  • 点击
  • 鼠标
滚动时是否触发:

  • 穆斯敦
  • 触控启动
  • 接触端
简单的解决方案就是坚持点击事件。但我们发现,在某些黑莓设备上,touchstart和它触发click或mouseup之间有一个非常明显的延迟。此延迟严重到足以使其在这些设备上无法使用

因此,我们还有其他选择。但是,使用这些选项,您可以滚动列表,而无需触发您触摸的行来启动滚动


解决这个问题的最佳做法是什么

您基本上想要做的是检测什么是刷卡,什么是点击

我们可以设定一些条件:

  • 滑动是指当您在点
    p1
    ,然后将手指移动到点
    p2
    ,同时手指仍在屏幕上,然后松开
  • 单击是指在同一图元上点击“开始点击”和“结束点击”
  • 因此,如果存储了
    touchStart
    发生位置的坐标,则可以在
    touchsend
    处测量差异。如果这个变化足够大,考虑它是一个刷卡,否则,认为它是一个点击。 另外,如果你想做得很整洁,你也可以在
    触摸移动时用手指检测你在哪个元素上“悬停”,如果你还没有在开始点击的元素上,你可以运行
    点击取消
    方法来删除突出显示等

    // 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);
    
    然后,您还必须将侦听器添加到可滚动元素中,但您不必担心如果手指在
    touchStart
    touchsend
    之间移动会发生什么

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

    //Simon A.

    这是我最终想到的,它允许通过滑动滚动项目列表,但也允许通过点击“触发”每个项目。此外,您还可以使用键盘(使用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()
    }
    });
    
    $(文档)
    //记录touchstart交互的位置
    .bind('touchstart',函数(e){
    touchStartPos=$(窗口).scrollTop();
    })
    //记录touchend交互的位置
    .bind('touchend',函数(e){
    //计算页面在这两者之间移动的距离
    //触摸开始和结束。
    var distance=touchStartPos-$(窗口).scrollTop();
    var$clickableItem;//如果不是刷卡,我希望可以单击的项目
    //为以下设备添加此类:
    //将在之后触发单击事件
    //touchend事件结束。此
    //告诉单击事件我们已经
    //已经做了一些事情,所以不要重复
    $clickableItem.addClass(“触摸”);
    如果(距离>20 | |距离<-20){
    //距离超过20像素
    //所以我们假设他们是有意的
    //滑动以滚动列表,然后
    //不选择行。
    }否则{
    //我们假设那是一个水龙头
    您想要什么样的函数来触发GerontaporClick()
    }
    });
    $($clickableItem).live('click',函数(e){
    //对于任何非触摸设备,我们需要
    //仍然应用单击事件的步骤
    //但我们先来看看
    //如果有之前的接触
    //通过检查类来创建事件
    //那是触摸事件留下的。
    if($(this.hasClass(“触摸”)){
    //此项目的事件已通过触摸触发
    //因此,我们不会调用该函数并为
    //下一步是删除类
    $(此).removeClass(“触摸”);
    }否则{
    //没有任何接触事件,我们正在
    //而是使用鼠标或键盘
    您想要什么样的函数来触发GerontaporClick()
    }
    });
    
    我做了一些不同的工作。它肯定不是很优雅,当然也不适合大多数情况,但它对我有效

    我一直在使用jQuery的toggleSlide()打开和关闭输入div,并在touchstart上启动幻灯片。问题是,当用户想要滚动时,触摸的div就会打开。为了阻止这种情况发生,(或者在用户注意到之前将其反转),我在文档中添加了一个touchlide事件,该事件将关闭最后一个触摸的div

    更深入地讲,下面是一段代码片段:

    var lastTouched;
    
    document.addEventListener('touchmove',function(){
        lastTouched.hide();
    });
    
    $('#button').addEventListener('touchstart',function(){
        $('#slide').slideToggle();
        lastTouched = $('#slide');
    });
    
    全局变量存储最后一次触摸的div,如果用户刷卡,document.touchmove事件会隐藏该div。有时会出现一个div闪烁,但它可以满足我的需要,并且非常简单。

    引用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");
    });
    

    我遇到了这个优雅的解决方案,它使用jQuery的效果非常好。我的问题是阻止列表项在滚动期间调用其触摸开始事件。这也适用于刷卡

    function touchScroll(e){
    
        var objTarget = $(event.target);
    
        if(objTarget.attr('data-object')){
            var fn = objTarget.attr('data-object'); //function to call if tapped    
        }   
    
        if(!touchEnabled){// default if not touch device
            eval(fn);
            console.log("clicked", 1);
            return;
        }
    
        $(e.target).on('touchend', function(e){
            eval(fn); //trigger the function
            console.log("touchEnd")      
            $(e.target).off('touchend');
        });
    
        $(e.target).on('touchmove', function(e){
            $(e.target).off('touchend');
            console.log("moved")
        }); 
    
    }
    
  • 将touchstart绑定到将使用类“listObject”滚动或滑动的每个项目

    $('.listObject').live('touchstart', touchScroll);
    
  • 然后为每个项分配一个数据对象attr,定义要调用的函数

    <button class='listObject' data-object=alert('You are alerted !')>Alert Me</button>
    

    我也有同样的问题,这里有一个对我有效的快速解决方案

    $(document).on('touchstart', 'button', function(evt){ 
        var oldScrollTop = $(window).scrollTop();
        window.setTimeout( function() {
            var newScrollTop = $(window).scrollTop();
            if (Math.abs(oldScrollTop-newScrollTop)<3) $button.addClass('touchactive');
        }, 200);
    });
    
    $(文档).on('touchstart','button',函数(evt){
    var oldcollScrollTop=$(窗口).scrollTop();
    setTimeout(函数(){
    var newScrollTop=$(window.scrollTop();
    
    if(Math.abs(oldScrollTopNewsCrollTop)这些解决方案中的一些对我有效,但最终我发现这个轻量级库的设置更简单

    Tocca.js:


    它非常灵活,可以检测触摸、刷卡、双击等。我使用这段代码,只有在未刷卡时才触发按钮(在触摸端):

    var startY;
    var yDistance;
    
    function touchHandler(event) {
        touch = event.changedTouches[0];
        event.preventDefault();
    }
    
    $('.button').on("touchstart", touchHandler, true);
    $('.button').on("touchmove", touchHandler, true);
    
    $('.button').on("touchstart", function(){
        startY = touch.clientY;
    });
    
    $('.button').on('touchend', function(){
    
        yDistance = startY - touch.clientY;
    
        if(Math.abs(yDist) < 30){
    
            //button response here, only if user is not swiping
            console.log("button pressed")
        }
    });
    
    var touchmoved;
    $('button').on('touchend', function(e){
        if(touchmoved != true){
            // button click action
        }
    }).on('touchmove', function(e){
        touchmoved = true;
    }).on('touchstart', function(){
        touchmoved = false;
    });
    
    var elems = $('YOURMULTISELECTOR'); // selector for multiple elements
    elems.unbind('mousdown pointerdown touchstart touchmove mouseup pointerup touchend');
    var elem = null;
    elems.on('mousdown pointerdown touchstart', function (e) {
        elem = yourSingleSelector(e);
    }).on('touchmove', function (e) {
        elem = null;                
    }).on('mouseup pointerup touchend', function (e) { 
        if (elem == yourSingleSelector(e)) {                    
            // do something
        }
    });