簡體   English   中英

如何檢測元素外的touchend事件

[英]How to detect touchend event outside of an element

我正在嘗試處理按鈕點擊。 “按鈕”是一個自定義div,也可以包含子項。 當用戶在元素內單擊並釋放時,應觸發單擊回調。 如果用戶單擊內部然后拖動並釋放到外部,則處理程序不應該觸發。 我需要在桌面和移動設備上使用它,因此我正在使用mousedown/mouseuptouchstart/touchend事件。

即使用戶在外面發布,我也需要將按鈕類從“按下”更改為“正常”,因此我需要添加一個偵聽器來捕獲文檔上的發布事件:

    var $myElement = $("#myelement"); //This is a div and can also contain children.

    $myElement.on("mousedown touchstart", function(e){  

        $(this).addClass("pressed");    

        $(document).on("mouseup touchend", function listener(e){
            $myElement.removeClass("pressed");

            $(document).off("mouseup touchend", listener);

            var $target = $(e.target);
            if ($target.is($myElement) || $target.parents().is($myElement)){        
                //FIXME
                alert("Inside!");

                //do something here
                return false;
            } else {
                //FIXME
                alert("Outside!");

                //let event bubble
            }
        });

        return false;
    });

它適用於點擊,但它不能按預期的方式使用觸摸事件。 我在Chrome for Android中進行了測試,當按下元素時,然后拖出“Inside!” 警報顯示。

問題出在這種情況:

if ($target.is($myElement) || $target.parents().is($myElement)){

我正在嘗試檢查按鈕或任何一個孩子是否發生了touchend事件。 如果按鈕沒有子節點,則單擊它然后釋放到外部時,OR子句的第一部分將解析為true。 如果按鈕有子項並且我單擊子項,然后在屏幕的任何其他部分釋放,則該子句的第二部分為真。

這段代碼有什么問題?

提前致謝。

UPDATE
我也在BlackBerry 10中對它進行了測試,結果相同。 顯然, touchend事件的目標是按鈕(或孩子們),即使我在外面點擊也是如此。 這是它應該如何工作?

UPDATE
這就是原因。 這就是W3C文檔對此事件的評價

此觸摸事件的目標必須與此觸摸點放置在曲面上時觸摸touchstart事件的元素相同,即使觸摸點已移出目標元素的交互區域之外。

這對我沒有意義,但無論如何這解釋了我的問題。 我假設在手指被釋放的元素上調用touchend事件。 是否可以使用不同的方法檢測外部的手指釋放?

UPDATE
我試圖使用document.elementFromPoint獲取touchevent的坐標以獲取元素。 問題是此事件不包含坐標( changedTouchestouches列表為空)。 我已經徹底檢查了調試器中的事件,除了原始事件之外,沒有辦法從中檢索coords。 然后我想我可以緩存最后一次touchmove事件並從那里獲得coords,但是這個事件再次沒有自己的坐標! 為什么地球上這兩個事件存在時它們是無用的? 我已經在iOS,Android和BB10中測試了這種方法,結果相同。

我已經放棄了。 即使用戶點擊外面,我也會調用回調。 我不敢相信它是2013年的家伙而且沒有(簡單)這樣做的方式? 我可以使用拖放API,但根據是在移動(愛是愛移動Web開發)不支持的。

最后(幾乎)讓它在BB10和Android中運行。 我離開的問題更新問題線索,所以綜上所述: touchend事件目標是一樣的touchstart ,並談到無坐標(出於某種原因,API設計師決定在“隱藏”他們originalEvent財產:)。 所以我從changedTouches[0].pageXchangedTouches[0].pageY檢索觸摸結束坐標,然后使用document.elementFromPoint獲取釋放手指的元素。 (在使用事件坐標輸入此方法之前,必須將滾動偏移添加到x和y)。 然后,如果該點的元素是按鈕(或者是它的子元素),我處理點擊。

    var $myElement = $("#myelement"); //This is a div and can also contain children.
    var startEvent = touchDevice() ?  "touchstart" : "mousedown";
    var releaseEvent = touchDevice() ?  "touchend" : "mouseup";

    $myElement.on(startEvent, function(e){  

        $(this).addClass("pressed");    

        $(document).on(releaseEvent, function listener(e){
            $myElement.removeClass("pressed");

            $(document).off(releaseEvent, listener);

            var $target = null;
            if(e.type === "mouseup"){
                 $target = $(e.target);         
            } else {            
                var x = e.originalEvent.changedTouches[0].pageX - window.pageXOffset;
                var y = e.originalEvent.changedTouches[0].pageY - window.pageYOffset;
                var target = document.elementFromPoint(x, y);

                if(target){
                    $target = $(target);
                }           
            }

            if ($target !== null && ($target.is($myElement) || $target.parents().is($myElement))){      
                //FIXME
                alert("Inside!");

                //callback here
                return false;
            } else {
                //FIXME
                alert("Outside!");
            }
        });

        return false;
    });

現在我遇到了一個新問題:在iOS中某種程度上,點擊事件是重復的。 但這值得一個不同的問題(如果不存在的話)。

你需要一個不同的,更整潔的方法。

分別為桌面和移動設備實現onmousemove和ontouchmove。

btn_obj.onmousemove = CancelOnClick (this);

實現CancelOnClick函數將標志從按下設置為正常。 它可以幫助您遠離所有元素及其基於子元素的條件。

希望有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM