2013/03/13更新

[JS] スマホでclickイベントより早くユーザーのタップ動作に反応する

このエントリーをはてなブックマークに追加      

こんにちは、@yoheiMuneです。
最近スマホでのWebアプリを開発することが多いのですが、タップへの反応速度を上げるこんな方法はどうかなぁと考えたので、ブログに書きたいと思います。

画像


スマホでタップにより速く反応したい

スマホ用Webアプリの開発で、ユーザーがタップした際にJSを起動したい(例えばダイアログを表示したいなど)という要件があるとします。
その場合に、タップ対象の要素のonclickにイベントをバインドして処理をすることが多いかと思います。
こんな感じ。
var btn = document.getElementById('someBtn');
btn.addEventListener('click', function() {
	// タップされた際の処理
});
でもこれだと確かに反応するのですが、ユーザーがタップしてからイベントが発火するまでに時間が空いてしまい、遅いのです。
だったらtouchEndといったイベントを使えばいいのではと考えて実装したのですが、 それらを使うと、画面スクロールのためにタップしていた指にすら反応してしまい、誤操作が増えてしまいますた。
var btn = document.getElementById('someBtn');
btn.addEventListener('touchend', function() {
	// スクロールのためのタップにも反応してしまう。
});

ということで、touchend並みに反応速度が良くて、スクロールのためのタップには反応しない作りは出来ないものかと思い、 今回のサンプルを作ってみました。



onclickより速くユーザータップに反応する実装

ということで、以下のようなものを作成してみました。
仕組みは簡単で、touchstartでタップを認識して、touchmoveが発火しない(スクロール的なことが起きていない)場合には、 touchendでしていされたイベントを発火させるという実装です。

今回はjQueryを使っていたので、jQueryの拡張として実装してみました。
// spTouchというメソッドを定義
// 引数にユーザータップ時に発火させたいイベントを指定する。
$.fn.extend({
  spTouch: function(actionFn) {
    var isTouch = false;
    $(this)
      .on('touchstart', function() {isTouch = true;})
      .on('touchmove', function() {isTouch = false;})
      .on('touchend', function() {
        if (isTouch) {
          // 発火させたいイベントを発火させる。
          // 引数に対象DOMを指す要素を渡す。
          actionFn(this);
        }
      });
    return this;
  }
});

// 実際に使ってみた例
$('#someBtn').spTouch(function(target) {
	alert('elementName: ' + target.elementName);
});

こんな感じで、onclickよりは速く動作するイベントを定義してみました。
このイベントでタップイベントに反応すると、clickよりは快適な感じです☆



上記コードの問題点

ただ、以下のような問題点もありますので、まだまだ改良が必要そうです。

  • イベントをunbindする方法が定義できていない。Backboneなどのメモリ管理が大切なやつでは使いづらい。
  • touchmoveが一度でも発火したらイベントキャンセルは厳しい判定かも。ある程度の誤差は許容する実装が良いかも。
  • spTouchで複数のイベントをバインドできない。
  • 発火させたいイベントのthisをバインドしていないし、touchendで保持できるeventオブジェクトへの参照も無い。

いろいろと問題山積みです。 ただ今のところ上記の不備を対応しない上記の簡単なコードでもいい感じに動いているので良いかなぁとも思ったりもしてますorz。。。



最後に

iOSネイティブアプリの開発をしていると、Webアプリの反応の悪さが特に気になってしまいました。 他のWebアプリとかどうしているんだろうと気になる今日この頃。 aタグやsubmit、labelタップなどはブラウザネイティブの挙動に任せれば良いかなぁと思うのですが、JS発火も早くしたいなぁと思う今日この頃でした。

最後までご覧頂きましてありがとうございました。





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。