【问题标题】:How to get touchEnd to behave just like mouseUp?如何让 touchEnd 表现得像 mouseUp?
【发布时间】:2012-07-11 07:12:26
【问题描述】:

mouseUptouchEnd 上,我想获取发生该事件的元素的引用。

Demo

在这个例子中,你需要点击一个元素,拖动鼠标并释放到另一个元素上。释放鼠标时,该元素的背景将变为红色。我的代码在鼠标事件上可以正常工作,但在触摸设备上却不行。

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

我需要进行哪些更改才能使触摸事件与鼠标事件完全一样?

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

}

【问题讨论】:

标签: javascript html css touch dom-events


【解决方案1】:

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

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

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

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

为此我使用了document.elementFromPoint(mdn link)。这是CSSOM spec 提供给我们的那些黄金但相当未知的方法之一。

这是fiddle

【讨论】:

  • 很棒的发现!我可以确认这适用于带有 Chrome 的三星 Galaxy Tab。
  • 也适用于我的 x 上的 opera、stock android 浏览器和 chrome。
  • 是的.. 我认为这是一个很好的解决方案.. :) 但我不知道对 elementFromPoint 的支持..
  • 谢谢,它成功了。但是,它不适用于没有悬停的简单点击,因此我还必须将 onDocumentTouchMove() 绑定到 touchstart 事件。
【解决方案2】:

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

我尚未对此进行广泛测试,但它似乎至少可以在移动 Safari 上运行 touchStarttouchEnd 事件。

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • @isaac this 这里仍然是 touchstart 被触发的元素,因此它不是一个可行的解决方案。
    猜你喜欢
    • 2018-12-25
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 2015-02-08
    • 2012-02-14
    • 2017-10-19
    • 2018-02-10
    • 1970-01-01
    相关资源
    最近更新 更多