将短滑动视为咔嗒声

时间:2018-01-23 22:15:28

标签: javascript events touch swipe dom-events

我有一个移动网络应用,它在按钮等上使用了很多click事件处理程序。如果用户确实"点击" (即" touchdown-touchup")按钮。但是,如果用户执行了短暂滑动,则click事件不会触发。这会引起我的用户的很多抱怨,即该应用无法注册点击/点按,其他应用也能正常运行。

当然,我可以在ontouchstartontouchend中获取触摸的坐标并计算距离 - 但我还需要知道该距离是否低于浏览器将视为&的最大距离#39;单击&#39 ;.我 not 想要切换到使用touchstart / touchend事件而不是点击。

我曾经使用fastclick.js库来处理过去的点击/点击,但现在使用原生'点击' touch-action: manipulation的事件。是否有任何方法可以指定/控制手指在按钮上的最大移动仍然可以注册为“点击”?

根据评论

更新。该应用程序非常庞大,整个过程中有数百个(如果不是数千个)事件处理程序分配(该应用程序已在过去8年中开发)。改变所有这些是不切实际的,因此我正在寻找一种解决方案,允许我在全局范围内设置一次阈值或使用类似全局的touchstart / touchend处理程序解决问题。

1 个答案:

答案 0 :(得分:1)

我认为这是一个有趣的问题,所以我为你解决了这个问题。在某种程度上,它与click发生时阻止dblclick事件的问题有些相似。

使用距离阈值进行"短暂滑动"至少对我来说似乎是有问题的,因为阈值距离可能与系统有关。而不是我决定触发,如果"点击"事件真的发生了。我使用mousedown作为模拟touchstartmouseup作为模拟touchendmouseup始终在click之前发生,因此在这方面类似于touchend

通常,如果你"点击" (mousedown)在元素上,然后将鼠标指针移离元素,click事件不会发生。这很像你描述的那种短暂滑动"。在一定距离之后,click事件才会发生。下面的代码将为按钮发送click事件,即使你已经在它上面移动,将指针移开它然后鼠标按下。我相信如果您将其用于touchstarttouchend,这可以解决问题



// The pre-exisiting click handler
function handleClick(ev) {
    console.log('button clicked. do work.');
}

document.getElementById('theButton').addEventListener('click', handleClick);

// our global "touch" handlers
var touchHandler = {
    curPending: null,
    curElem: null,

    handleTouch: function handleTouch(ev) {
        switch (ev.type) {
            case 'mousedown':
                // capture the target that the click is being initiated on
                touchHandler.curElem = ev.target;
                
                // add an extra click handler so we know if the click event happens
                ev.target.addEventListener('click', touchHandler.specialClick);
                break;

            case 'mouseup':
                // start a pending click timer in case the click event doesn't happen
                touchHandler.curPending = setTimeout(touchHandler.pendingClick, 1);
                break;
        }
    },

    specialClick: function(ev) {
        // the click event happened 
        // clear our extra handler 
        touchHandler.curElem.removeEventListener('click', touchHandler.specialClick);
        
        // make sure we don't send an extra click event
        clearTimeout(touchHandler.curPending);
    },

    pendingClick: function() {
        // we never heard the click event
        
        // clear our extra handler 
        touchHandler.curElem.removeEventListener('click', touchHandler.specialClick);

        // trigger a click event on the element that started it all
        touchHandler.curElem.click();
    }
};

// using "mousedown" as "touchstart" and "mouseup" as "touchend"
document.addEventListener('mouseup', touchHandler.handleTouch);
document.addEventListener('mousedown', touchHandler.handleTouch);

<p>I work when clicked normally but I also work when 
mousedown, drag pointer off me, mouseup</p>
<button id="theButton">Click Me</button>
&#13;
&#13;
&#13;