从触摸事件生成鼠标事件
好的,我看到这个问题已经有一段时间了,没有人提供答案,我来提供一个。
与鼠标事件不同,触摸事件涉及许多与 UI 的接触点。为了适应这一点,触摸事件提供了一个触摸点的数组。由于鼠标不能同时处于两个位置,最好将这两种交互方法分别处理,以获得最佳的用户体验。由于您没有询问如何检测设备是触摸还是鼠标驱动的,我已经留给其他人来问。
处理两者
鼠标和触摸事件可以共存。在没有其中之一的设备上添加鼠标或触摸事件的侦听器不是问题。缺少的输入界面只是不会生成任何事件。这使得很容易为您的页面实现透明解决方案。
关键在于你喜欢哪个界面,并在该界面不可用时模拟该界面。在这种情况下,我将从创建的任何触摸事件中模拟鼠标。
通过编程创建事件。
代码使用 MouseEvent 对象创建和分派事件。它很容易使用,事件与真实的鼠标事件无法区分。有关 MouseEvent 的详细说明,请转到 MDN MouseEvent
最基本的操作。
创建一个鼠标单击事件并将其分派到文档中。
var event = new MouseEvent( "click", {'view': window, 'bubbles': true,'cancelable': true});
document.dispatchEvent(event);
您还可以将事件分派给单个元素。
document.getElementById("someButton").dispatchEvent(event);
监听事件就像监听实际鼠标一样。
document.getElementById("someButton").addEventListener(function(event){
));
MouseEvent
函数的第二个参数是您可以添加有关事件的其他信息的位置。例如,
clientX
和
clientY
是鼠标的位置,或者
which
或
buttons
表示按下的按钮。
如果您曾经查看过
mouseEvent
,您将知道有很多属性。因此,发送到鼠标事件中的内容将取决于事件侦听器使用什么。
触摸事件。
触摸事件与鼠标类似。有
touchstart
、
touchmove
和
touchend
。它们不同之处在于它们提供一个位置数组,每个接触点对应一个位置。不确定最大值是多少,但对于这个答案,我们只对一个感兴趣。有关完整详情,请参见
MDN touchEvent。
我们需要做的是,对于仅涉及一个接触点的触摸事件,我们希望在相同位置生成相应的鼠标事件。如果触摸事件返回多个接触点,则我们无法知道它们的意图焦点在哪里,因此我们将简单地忽略它们。
function touchEventHandler(event){
if (event.touches.length > 1){ // Ignor multi touch events
return;
}
}
现在我们知道,通过触摸单个联系人,我们可以根据触摸事件中的信息创建鼠标事件。
最基本的情况是这样的:
touch = event.changedTouches[0];
if(type === "touchmove"){
mouseEventType = "mousemove";
}else
if(type === "touchstart"){
mouseEventType = "mousedown";
}else
if(type === "touchend"){
mouseEventType = "mouseup";
}
var mouseEvent = new MouseEvent(
mouseEventType,
{
'view': event.target.ownerDocument.defaultView,
'bubbles': true,
'cancelable': true,
'screenX':touch.screenX,
'screenY':touch.screenY,
'clientX':touch.clientX,
'clientY':touch.clientY,
});
touch.target.dispatchEvent(mouseEvent);
现在您的鼠标监听器将接收
mousedown
,
mousemove
,
mouseup
事件,当用户在设备上仅在一个位置触摸时。
遗漏点击
到目前为止一切顺利,但有一个缺少的鼠标事件是必须的。 "onClick" 我不确定是否有等效的触摸事件,只是作为练习,我看到我们所拥有的足够信息来决定一组触摸事件是否可以视为单击。
这将取决于开始和结束触摸事件之间的距离有多远,超过几个像素就会成为拖动。它还会取决于持续时间。(虽然不同于鼠标)我发现人们倾向于轻击以进行单击操作,而鼠标可以保持按下,在释放时用于确认,或者拖动取消,这不是人们使用触摸界面的方式。
因此,我记录
touchStart
事件发生的时间。
event.timeStamp
和开始位置。然后在
touchEnd
事件中,我查找移动的距离和时间。如果它们都在我设置的限制范围内,我还会生成鼠标单击事件和鼠标释放事件。
这是将触摸事件转换为鼠标事件的基本方法。
一些代码
下面是一个名为mouseTouch的小型API,它执行我刚才解释的操作。它涵盖了简单绘图应用程序所需的最基本的鼠标交互。
var touchMouse = (function(){
"use strict";
var timeStart, touchStart, mouseTouch, listeningElement, hypot;
mouseTouch = {};
mouseTouch.clickRadius = 3;
mouseTouch.clickTime = 200;
mouseTouch.generateClick = true;
mouseTouch.clickOnly = false;
mouseTouch.status = "Started.";
if(typeof Math.hypot === 'function'){
hypot = Math.hypot;
}else{
hypot = function(x,y){
return Math.sqrt(Math.pow(x,2)+Math.pow(y,2));
};
}
function triggerMouseEvemt(type,fromTouch,fromEvent){
var mouseEvent = new MouseEvent(
type,
{
'view': fromEvent.target.ownerDocument.defaultView,
'bubbles': true,
'cancelable': true,
'screenX':fromTouch.screenX,
'screenY':fromTouch.screenY,
'clientX':fromTouch.clientX,
'clientY':fromTouch.clientY,
'offsetX':fromTouch.clientX,
'offsetY':fromTouch.clientY,
'ctrlKey':fromEvent.ctrlKey,
'altKey':fromEvent.altKey,
'shiftKey':fromEvent.shiftKey,
'metaKey':fromEvent.metaKey,
'button':0,
'buttons':1,
});
fromTouch.target.dispatchEvent(mouseEvent);
}
function emulateMouse(event) {
var type, time, touch, isClick, mouseEventType, x, y, dx, dy, dist;
event.preventDefault();
type = event.type ;
if (event.touches.length > 1){
if(touchStart !== undefined){
triggerMouseEvent("mouseup",event.changedTouches[0],event);
}
touchStart = undefined;
return;
}
mouseEventType = "";
isClick = false;
if(type === "touchmove" && !mouseTouch.clickOnly){
touch = event.changedTouches[0];
mouseEventType = "mousemove";
}else
if(type === "touchstart"){
touch = touchStart = event.changedTouches[0];
timeStart = event.timeStamp;
mouseEventType = !mouseTouch.clickOnly?"mousedown":"";
}else
if(type === "touchend"){
touch = event.changedTouches[0];
mouseEventType = !mouseTouch.clickOnly?"mouseup":"";
if(touchStart !== undefined && mouseTouch.generateClick){
time = event.timeStamp - timeStart;
if(time < mouseTouch.clickTime){
dx = touchStart.clientX-touch.clientX;
dy = touchStart.clientY-touch.clientY;
dist = hypot(dx,dy);
if(dist < mouseTouch.clickRadius){
isClick = true;
}
}
}
}
if(mouseEventType !== ""){
triggerMouseEvent(mouseEventType,touch,event);
}
if(isClick){
triggerMouseEvent("click",touch,event);
}
}
function removeTouchEvents(){
listeningElement.removeEventListener("touchstart", emulateMouse);
listeningElement.removeEventListener("touchend", emulateMouse);
listeningElement.removeEventListener("touchmove", emulateMouse);
listeningElement = undefined;
}
function startTouchEvents(element){
if(listeningElement !== undefined){
throw new ReferanceError("touchMouse says!!!! API limits functionality to one element.");
}
if(element === undefined){
element = document;
}
listeningElement = element;
listeningElement.addEventListener("touchstart", emulateMouse);
listeningElement.addEventListener("touchend", emulateMouse);
listeningElement.addEventListener("touchmove", emulateMouse);
}
mouseTouch.start = startTouchEvents;
mouseTouch.stop = removeTouchEvents;
return mouseTouch;
})();
touchMouse.start();
<input value="touch click me" id="touchButton" type="button"></input>
var el = document.getElementById("touchButton");
if(el !== null){
touchMouse.clickOnly = true;
touchMouse.start(el);
}
<canvas id="touchCanvas"></canvas>
var el = document.getElementById("touchButton");
if(el !== null){
touchMouse.generateClick = false;
touchMouse.start(el);
}
touchMouse.stop();
touchMouse = undefined;
希望这能对你的代码有所帮助。