2013年9月1日日曜日

スマートフォンでタップイベントの反応を良くする。(JavaScript)

新生FF14やってます、楽しいですね。…しかし、ログインできないっ!金曜日はいけたのに、土日はまったくログインできないです。(涙)ネット上ではログインする事が目的になってしまったログインオンラインなんて言われてますw。待っても待ってもログインできないので、ブログ書きます。

ここから本題。

clickイベントにイベントハンドラを設定すると、スマホではタップしたときの反応が鈍い感じになってしまいます。click周りのイベントには、click, touchstart, touchend, mousedown, mouseupなどがありますが、スマホではtouchstart, またはtouchendで判定するようにするとレスポンスを早くする事が出来ます。

ただ、touchstartイベントで処理を書くとスクロールしようとする時にも反応してしまいます。スクロールする必要のない場合は、ここで処理しても良いでしょう。
また、touchendイベントの場合も、他の要素に触れた状態で、指を滑らせてから離すと反応してしまい本来のタップ判定とは異なるものになるでしょう。

そこで、touchstart時にフラグを持たせ、touchend時に判定する処理が必要になります。 
※下記サンプルコード参照。
$(function(){
    // イベント登録
    $('li').on('touchstart touchmove touchend', function(event){
        // タッチスタートでフラグを設定
        if ('touchstart' == event.type){
            $(this).attr('data-touchstarted', '');
            return;
        }

        // タッチムーブが発生したら、フラグを消す。(タップと判定させない為)
        if ('touchmove' == event.type){
            $(this).removeAttr('data-touchstarted');
            return;
        }

        // タッチエンド時にフラグがあれば、タップと判定する。
        if ('undefined' != typeof $(this).attr('data-touchstarted')){

            // ここでタップ時のイベントハンドラを呼び出す。
            onListItemTapped.call(this, event);

            // フラグを削除
            $(this).removeAttr('data-touchstarted');
        }
    });

    // PCからのクリックにも対応
    $('li').on('click', function(event){
        onListItemTapped.call(this, event);
    });
});


/*
* タップ、クリック時の処理
*/
function onListItemTapped(event){
    event.preventDefault();

    // TODO: タップ時の処理
    console.log( event.type );
}

サンプルはli要素にタップイベントを付与するものです。
touchstart時にフラグを属性として持たせています。touchmoveが発生した場合はタップとは判定しないようにフラグを消します。touchendが発生した時にフラグが残っていればタップしたと判定できます。

mouseup, mousedownイベントでも、同じ処理をすれば出来ますがclickイベントと同じように反応が鈍くなってしまいます。

イベントハンドラをcallメソッドで呼んでいるのは、thisをハンドラ関数に引き継ぐためです。また、PCでも動作するようclickイベントも登録しているので、スマホの場合ハンドラ関数が2回呼ばれます。preventDefault()を呼ぶ事で、それらの処理ダブりを防止できます。

0 件のコメント:

コメントを投稿