JavaScript将触摸事件映射到鼠标事件

时间:2009-10-05 01:43:39

标签: javascript javascript-events touchscreen

我正在使用与鼠标移动事件一起操作的YUI滑块。我想让它回应touchmove事件(iPhone和Android)。当touchmove事件发生时,如何生成鼠标移动事件?我希望只是通过在顶部添加一些脚本,touchmove事件将被映射到鼠标移动事件,我将不必使用滑块更改任何内容。

5 个答案:

答案 0 :(得分:102)

我确信这就是你想要的:

function touchHandler(event)
{
    var touches = event.changedTouches,
        first = touches[0],
        type = "";
    switch(event.type)
    {
        case "touchstart": type = "mousedown"; break;
        case "touchmove":  type = "mousemove"; break;        
        case "touchend":   type = "mouseup";   break;
        default:           return;
    }

    // initMouseEvent(type, canBubble, cancelable, view, clickCount, 
    //                screenX, screenY, clientX, clientY, ctrlKey, 
    //                altKey, shiftKey, metaKey, button, relatedTarget);

    var simulatedEvent = document.createEvent("MouseEvent");
    simulatedEvent.initMouseEvent(type, true, true, window, 1, 
                                  first.screenX, first.screenY, 
                                  first.clientX, first.clientY, false, 
                                  false, false, false, 0/*left*/, null);

    first.target.dispatchEvent(simulatedEvent);
    event.preventDefault();
}

function init() 
{
    document.addEventListener("touchstart", touchHandler, true);
    document.addEventListener("touchmove", touchHandler, true);
    document.addEventListener("touchend", touchHandler, true);
    document.addEventListener("touchcancel", touchHandler, true);    
}

我已经捕获了触摸事件,然后手动触发了我自己的鼠标事件来匹配。尽管代码不是特别通用的,但是应该适应大多数现有的拖放库以及可能是大多数现有的鼠标事件代码应该是微不足道的。希望这个想法对于为iPhone开发Web应用程序的用户来说非常方便。

<强>更新

在发布此消息时,我注意到在所有触摸事件上调用preventDefault会阻止链接正常工作。拨打preventDefault的主要原因是阻止手机滚动,您只能通过touchmove回拨来拨打电话。这样做的唯一缺点是iPhone有时会在拖动原点上显示其悬停弹出窗口。如果我发现了一种防止这种情况的方法,我会更新这篇文章。

第二次更新:

我找到了关闭标注的CSS属性:-webkit-touch-callout

答案 1 :(得分:5)

根据@Mickey Shine的回答,Touch Punch提供了触摸事件到点击事件的映射。它是为了将这种支持放入jQuery UI而构建的,但是the code是提供信息的。

答案 2 :(得分:3)

对于将来回来的用户,可能会使用以下代码:

var eventMap = {};

(function(){
var eventReplacement = {
    "mousedown": ["touchstart mousedown", "mousedown"],
    "mouseup": ["touchend mouseup", "mouseup"],
    "click": ["touchstart click", "click"],
    "mousemove": ["touchmove mousemove", "mousemove"]
};


for (i in eventReplacement) {
    if (typeof window["on" + eventReplacement[i][0]] == "object") {
        eventMap[i] = eventReplacement[i][0];
    } 
    else {
        eventMap[i] = eventReplacement[i][1];
    };
 };
})();

然后在事件中使用如下:

$(".yourDiv").on(eventMap.mouseup, function(event) {
      //your code
}

答案 3 :(得分:2)

我终于找到了一种方法来使用Mickey的解决方案,而不是他的init函数。在这里使用init函数。

function init() {
    document.getElementById('filter_div').addEventListener("touchstart", touchHandler, true);
    document.getElementById('filter_div').addEventListener("touchmove", touchHandler, true);
    document.getElementById('filter_div').addEventListener("touchend", touchHandler, true);
    document.getElementById('filter_div').addEventListener("touchcancel", touchHandler, true);
}

如果您看到'filter_div'是我们有图表范围过滤器的图表区域,并且只在该区域中我们想要重写我们的触摸控件!

谢谢米奇。这是一个很好的解决方案。

答案 4 :(得分:1)

要使@Mickey的代码在Edge和Internet Explorer上运行,请在要进行模拟的元素的.css中添加以下行:

.areaWhereSimulationHappens {
    overflow: hidden;
    touch-action: none;
    -ms-touch-action: none;
}

这些行可防止边缘和IE的默认触摸。但是如果你将它添加到错误的元素,那么它也会禁用滚动(默认情况下会在边缘和触摸设备上的IE上发生)。