javascript 如何让 touchEnd 表现得像 mouseUp?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11427403/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 13:11:06  来源:igfitidea点击:

How to get touchEnd to behave just like mouseUp?

javascripthtmlcsstouchdom-events

提问by Sarath

On mouseUpor touchEndI want to get the reference of the element on which that event happened.

OnmouseUp或者touchEnd我想获取发生该事件的元素的引用。

Demo

演示

In this example, you need to click on one element, drag mouse and released over another element. When the mouse is released, that element's background will change to red. My code works correctly for mouse events, but not on touch devices.

在本例中,您需要单击一个元素,拖动鼠标并在另一个元素上释放。松开鼠标时,该元素的背景将变为红色。我的代码适用于鼠标事件,但不适用于触摸设备。

When the touchStartis on one element and the finger is released over another element, I'm getting only the reference to the first element.

touchStart在一个元素上并且手指在另一个元素上释放时,我只得到对第一个元素的引用。

What I need to change to make the touch events work exactly like the mouse events?

我需要改变什么才能使触摸事件与鼠标事件完全一样?

var isMouseDown = false;    


var panel1 = document.getElementById( 'panel1' );
var panel2 = document.getElementById( 'panel2' );

panel1.onmousedown = onDocumentMouseDown;
panel1.onmouseup = onDocumentMouseUp;
panel1.onmousemove = onDocumentMouseMove;   
panel1.addEventListener( 'touchstart', onDocumentTouchStart, false );
panel1.addEventListener( 'touchmove', onDocumentTouchMove, false );
panel1.addEventListener( 'touchend', onDocumentTouchEnd, false );

panel2.onmousedown = onDocumentMouseDown;
panel2.onmouseup = onDocumentMouseUp;
panel2.onmousemove = onDocumentMouseMove;
panel2.addEventListener( 'touchstart', onDocumentTouchStart, false );
panel2.addEventListener( 'touchmove', onDocumentTouchMove, false );
panel2.addEventListener( 'touchend', onDocumentTouchEnd, false );



function onDocumentMouseDown(event) {
    event.preventDefault();
    panel1.style.background="#2E442E";
    panel2.style.background="#5D855C";      
}

function onDocumentMouseUp(event) {
    event.preventDefault();
    this.style.background="#ff0000";
}

function onDocumentMouseMove( event ) {

}   

function onDocumentTouchStart( event ) {
    event.preventDefault();
    panel1.style.background="#2E442E";
    panel2.style.background="#5D855C";

}

function onDocumentTouchMove( event ) {     

}

function onDocumentTouchEnd( event ) {
    event.preventDefault();         
    this.style.background="#ff0000";        

}

采纳答案by zeusdeux

This was a fun question to tackle. Thanks for that. Here's what I have done. I have modified your touchmovehandler as such:

这是一个有趣的问题。感谢那。这是我所做的。我已经修改了你的touchmove处理程序:

   function onDocumentTouchMove(event) {
    onDocumentTouchMove.x = event.changedTouches[event.changedTouches.length - 1].clientX;
    onDocumentTouchMove.y = event.changedTouches[event.changedTouches.length - 1].clientY;
}

In this handler I'm saving the last co-ordinate that the user moved to. In all probability, this is the point at which the user took his finger, nose, knuckle, stylus, etc off the touch surface. These co-ordinates I then use in the handler for touchendto find the element that surrounds them.

在这个处理程序中,我保存了用户移动到的最后一个坐标。很有可能,这是用户将他的手指、鼻子、指关节、手写笔等从触摸表面移开的点。然后我在处理程序中使用这些坐标touchend来查找围绕它们的元素。

    function onDocumentTouchEnd(event) {
    event.preventDefault();
    var elem = document.elementFromPoint(onDocumentTouchMove.x, onDocumentTouchMove.y);
    elem.style.background = "#ff0000";
}

I have utilized the document.elementFromPoint(mdn link)for this purpose. It is one of those golden yet fairly unknown methods provided to us by the CSSOM spec.

为此,我使用了document.elementFromPoint(mdn 链接)。它是CSSOM 规范提供给我们的那些黄金但相当未知的方法之一

Here's the fiddle.

这是小提琴

回答by fuzic

From what it seems, this is intended behavior for touch events. However, I have a workaround!

从表面上看,这是触摸事件的预期行为。不过,我有一个解决方法!

I haven't tested this extensively, but it seems to work on mobile Safari for at least touchStartand touchEndevents.

我没有对此进行过广泛的测试,但它似乎至少适用于移动 SafaritouchStarttouchEnd事件。

Basically what we are going to do is capture all touch events on the document as they are in capture-phase (see http://www.w3.org/TR/DOM-Level-3-Events/). The handler for these events will find the DOM element at this location and re-send the event with the "correct" target.

基本上我们要做的是在文档上捕获所有处于捕获阶段的触摸事件(参见http://www.w3.org/TR/DOM-Level-3-Events/)。这些事件的处理程序将在此位置找到 DOM 元素,并使用“正确”目标重新发送事件。

It seems that the position of touchEndevents is not well defined, so I had to query the changedEventsarray to get the last-touched position. I am not sure if this works as-is for touchMoveevents et al.

似乎touchEnd事件的位置没有很好地定义,所以我不得不查询changedEvents数组以获取最后触摸的位置。我不确定这是否适用于touchMove事件等。

function rerouteTouch (evt) {
    if (evt.passthrough) { // Ignore if already rerouted
        return;
    }
    evt.stopPropagation();
    var newevt = document.createEvent('TouchEvent');
    newevt.initTouchEvent (
        evt.type,
        evt.bubbles,
        evt.cancelable,
        evt.view,
        evt.detail,
        evt.screenX,
        evt.screenY,
        evt.clientX,
        evt.clientY,
        evt.ctrlKey,
        evt.altKey,
        evt.shiftKey,
        evt.metaKey,
        evt.touches,
        evt.targetTouches,
        evt.changedTouches,
        evt.scale,
        evt.rotation);
    newevt.passthrough = true; // Only reroute once

    var target;
    var x = (evt.type === 'touchend') ? evt.changedTouches[0].pageX : evt.pageX;
    var y = (evt.type === 'touchend') ? evt.changedTouches[0].pageY : evt.pageY;

    if (document !== (target = document.elementFromPoint(x, y))) {
        target.dispatchEvent(newevt);
    }
}

document.addEventListener( 'touchstart', rerouteTouch, true); // Third arg is true to indicate capture-phase
document.addEventListener( 'touchend', rerouteTouch, true); 

...

// Your event handlers here

Here's a jsfiddle which works as expected on mobile safari for me: http://jsfiddle.net/DREer/12/

这是一个 jsfiddle,它在我的移动 safari 上按预期工作:http: //jsfiddle.net/DREer/12/

回答by Isaac Gonzalez

Perhaps if you can include jQuery into your program you can do something like this:

也许如果您可以将 jQuery 包含到您的程序中,您可以执行以下操作:

$('#itemId').on('touchEnd',function(){ this.trigger('mouseUp') });

I'm not sure if jQuery out of the box supports this events, but you can always try jQuery movil, hope it helped

我不确定开箱即用的 jQuery 是否支持此事件,但您可以随时尝试 jQuery movil,希望它有所帮助