52

モバイルでも表示可能で、タッチスタートとマウスダウンの両方でアクションをバインドする必要があるWebサイトでの作業。

このように見えます

 $("#roll").bind("mousedown touchstart", function(event){

 someAction();

iPhoneでは問題なく動作しますが、Androidでは2回応答します。

event.stopPropagation();
event.preventDefault();

このコードを追加すると、Android Chromeで修正されましたが、Androidのデフォルトブラウザでは修正されませんでした。すべてのAndroidの問題を解決できる他のトリックはありますか?

4

10 に答える 10

34
element.on('touchstart mousedown', function(e) {
    e.preventDefault();
    someAction();
});

preventDefault仕様に従って、イベントをキャンセルします

タッチスタートを取得しますが、キャンセルするとマウスダウンは発生しなくなります。受け入れられた答えが言うこととは反対に、stopPropagationそれがあなたが必要とするものでない限り、あなたは電話をする必要はありません。キャンセルしてもイベントは正常に伝播します。ブラウザはそれを無視しますが、フックは引き続き機能します。

Mozillaはこれについて私に同意します

タッチスタートまたはシリーズの最初のtouchmoveイベントでpreventDefault()を呼び出すと、対応するマウスイベントが発生しなくなります

編集:私は質問をもう一度読みました、そしてあなたはあなたがすでにこれをしました、そしてそれはAndroidのデフォルトのブラウザを修正しなかったと言います。基本的に同じことを行うので、受け入れられた回答がどのように役立ったかはわかりませんが、より複雑な方法で、イベント伝播のバグがあります(タッチスタートは伝播しませんが、クリックは伝播します)

于 2015-07-03T16:02:05.610 に答える
32

私はこの関数を使用しています:

//touch click helper
(function ($) {
    $.fn.tclick = function (onclick) {

        this.bind("touchstart", function (e) { 
            onclick.call(this, e); 
            e.stopPropagation(); 
            e.preventDefault(); 
        });

        this.bind("click", function (e) { 
           onclick.call(this, e);  //substitute mousedown event for exact same result as touchstart         
        });   

        return this;
    };
})(jQuery);

更新:マウスイベントとタッチイベントを一緒にサポートするように回答を変更しました。

于 2013-01-07T19:17:04.370 に答える
3

win8とchrome/firefoxに関するグレガーのコメントを考慮に入れると、skyisredのコメントは結局のところそれほど馬鹿げているようには見えません(:P @すべての嫌いな人)が、彼が提案したホワイトリストよりもブラックリストを使用したいのですが、Androidを除くタッチバインド:

var ua = navigator.userAgent.toLowerCase(),
isAndroid = ua.indexOf("android") != -1,
supportsPointer = !!window.navigator.msPointerEnabled,
ev_pointer = function(e) { ... }, // function to handle IE10's pointer events
ev_touch = function(e) { ... }, // function to handle touch events
ev_mouse = function(e) { ... }; // function to handle mouse events

if (supportsPointer) { // IE10 / Pointer Events
    // reset binds
    $("yourSelectorHere").on('MSPointerDown MSPointerMove MSPointerUp', ev_pointer);
} else {
    $("yourSelectorHere").on('touchstart touchmove touchend', ev_touch); // touch events
    if(!isAndroid) { 
        // in androids native browser mouse events are sometimes triggered directly w/o a preceding touchevent (most likely a bug)
        // bug confirmed in android 4.0.3 and 4.1.2
        $("yourSelectorHere").on('mousedown mousemove mouseup mouseleave', ev_mouse); // mouse events
    }
}

ところで:私はマウスイベントが常にトリガーされるとは限らないことを発見しました(stopPropagationとpreventDefaultが使用された場合)、特にタッチエンドイベントの直前に余分なmousemoveに気づいただけです...本当に奇妙なバグですが、上記のコードはすべてでそれを修正しました(テスト済みのOSX、Win、iOS 5 + 6、Android 2 + 4、それぞれネイティブブラウザ、Chrome、Firefox、IE、Safari、Opera(利用可能な場合)プラットフォーム。

于 2013-04-11T15:53:22.953 に答える
1

うわー、これと関連する質問には非常に多くの答えがありますが、どれも私にはうまくいきませんでした(Chrome、モービルレスポンシブ、マウスダウン+タッチスタート)。でも、これ:

(e) => {
  if(typeof(window.ontouchstart) != 'undefined' && e.type == 'mousedown') return;

  // do anything...
}
于 2019-03-14T15:10:05.683 に答える
0

このコードの使用を修正

var mobile   = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent); 
var start = mobile ? "touchstart" : "mousedown";
$("#roll").bind(start, function(event){
于 2012-12-01T21:46:39.873 に答える
0

jquery-fast-clickを試すことをお勧めします。私はこの質問や他の質問に対して他のアプローチを試しました。それぞれが1つの問題を修正し、別の問題を導入しました。ファストクリックは、Android、iOS、デスクトップ、およびデスクトップタッチブラウザ(うめき声)で初めて機能しました。

于 2013-09-05T20:20:23.940 に答える
0

このコードを記述し、jクエリパンチタッチjsを追加します。タッチイベントでマウスイベントをシミュレートします。

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

    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);    
} 
于 2015-10-06T09:23:02.873 に答える
0

このネイティブソリューションは私にとって最適に機能しました。

  1. touchstartグローバルのドキュメント設定にイベントを追加しますtouch = true
  2. mousedown / touchstartハンドラーで、タッチスクリーンが検出されたときにすべてのmousedownイベントを防止します。if (touch && e.type === 'mousedown') return;
于 2018-04-14T20:49:51.413 に答える
0

これは非常に古い質問ですが、同じ問題に遭遇し、デバイスのタイプをスニッフィングしないstopPropagation()preventDefault()またはスニッフィングしない別の解決策を見つけました。私は、デバイスがタッチ入力とマウス入力の両方をサポートしていることを前提として、このソリューションに取り組んでいます。

説明:タッチが開始されると、イベントの順序は1)touchstart2)touchmove3)touchend4)mousemove5)mousedown6)mouseup7)clickです。これに基づいて、touchstart(チェーンの最初)からclick(チェーンの最後)までのタッチインタラクションをマークします。このタッチ操作以外でamousedownが登録されている場合は、安全にピックアップできます。

以下はDartのロジックであり、jsで非常に複製可能である必要があります。

var touchStarted = false;
document.onMouseDown.listen((evt) {
  if (!touchStarted) processInput(evt);
});
document.onClick.listen((evt) {
  touchStarted = false;
});
document.onTouchStart.listen((evt) {
  touchStarted = true;
  processInput(evt);
});

ご覧のとおり、私のリスナーはに配置されていdocumentます。stopPropagation()したがって、他の要素にバブルアップできるように、preventDefault()これらのイベントを実行しないことが重要です。この解決策は、私が行動するための1つの相互作用を選び出すのに役立ち、それがあなたにも役立つことを願っています!

于 2022-02-16T01:21:05.453 に答える
-1

最善の方法は:

var hasTouchStartEvent = 'ontouchstart' in document.createElement( 'div' );

document.addEventListener( hasTouchStartEvent ? 'touchstart' : 'mousedown', function( e ) {
    console.log( e.touches ? 'TouchEvent' : 'MouseEvent' );
}, false );
于 2016-01-21T07:25:24.637 に答える