iPhoneのSafariでも "L"字フリックアクションでウインドウを閉じる。

iPhoneのWebブラウザ、今では「Sleipnir Mobile」をメインに使っています。

何が良いかと言うと、TouchPagingという機能。画面上で左右にフリックすれば隣のタブに移動できたり、"L"字を描けばそのタブを閉じることができたり。Safariよりアクション少なめで、これらの操作が完了できるのがスバラシイ。

で、Safariでもこの機能が使えたらなぁ…と思ったのでJavaScriptで作ってみた。タブ切り替えは無理そうなので、L字フリックでタブを閉じる機能のみ。

以下、ソースコード。いつもの如くやっつけコードなので、その辺りはご容赦を。

/* Lflick.js 
   Sleipnir Mobile の TouchPaging - L字フリックでタブを閉じる - の
   JavaScriptエミュレーション。iPhoneの Mobile Safariのみで動作。
   May 2011 (c) tyz_freefielder.jp http://freefielder.jp/  */

var lf_startX;
var lf_startY;
var lf_vflag = false;
var lf_hflag = false;
var lf_begintime;
var lf_moveX;
var lf_moveY;
var lf_isConfirm;

var Lflick = function( flag ){
 lf_isConfirm = flag;
 var ua = navigator.userAgent ;
 if( ua.indexOf( 'iPhone' ) != -1 && ua.indexOf( 'Safari' ) != -1 ){  // .....(1)
  if( ua.indexOf( 'Sleipnir') == -1){
   document.addEventListener( 'touchstart' , lf_touchstart , false);
   document.addEventListener( 'touchmove' , lf_touchmove ,false );
   document.addEventListener( 'touchend' , lf_touchend ,false );
  }
 }
}

var lf_touchstart = function( evt ){
 if( evt.touches.length == 1 ){     // .....(2)
  lf_vflag = true;
  lf_hflag = false;
  lf_startX = evt.touches[0].pageX - window.pageXOffset;
  lf_startY = evt.touches[0].pageY - window.pageYOffset;
  lf_begintime = new Date().getTime();
  lf_moveX = 0;
  lf_moveY = 0;
 }
};

var lf_touchmove = function( evt ){     // .....(3)
 var currenttime = new Date().getTime();
 lf_moveX = evt.touches[0].pageX -window.pageXOffset - lf_startX ;
 lf_moveY = evt.touches[0].pageY- window.pageYOffset - lf_startY ;
 if( lf_vflag ){
  if( lf_moveX > window.innerWidth/14 && lf_moveY > window.innerHeight/4 ){ // .....(4)
   lf_vflag = false;
   lf_hflag = true;
   lf_startY = evt.touches[0].pageY - window.pageYOffset;
  }
 }
 if( currenttime - lf_begintime > 700 ){ lf_vflag = false; lf_hflag = false ;}     // .....(5)
};

var lf_touchend = function(evt){      // .....(6)
 if( lf_hflag && lf_moveX > window.innerWidth/4 && Math.abs( lf_moveY ) < window.innerHeight/14 ){     //  ......(7)
  if( lf_isConfirm ){
   document.removeEventListener( 'touchstart' , lf_touchstart , false );     //  ......(8)
   document.removeEventListener( 'touchmove' , lf_touchmove , false );
   document.removeEventListener( 'touchend' , lf_touchend , false );
   var cfm = confirm( 'close window?' ) ;
   if( cfm){
    window.open();     //  ......(9)
    self.close();
   }else{
    document.addEventListener( 'touchstart' , lf_touchstart , false );
    document.addEventListener( 'touchmove' , lf_touchmove , false );
    document.addEventListener( 'touchend' , lf_touchend , false );
   }
  }else{
   window.open();
   self.close();
  }
 }
 lf_vflag = false;
 lf_hflag = false;
};


<body onload="Lflick( true||false );">な感じで呼び出します。引数が true だと、ウインドウを閉じる前に確認ダイアログを出して、false だと無言でウインドウを閉じます。

で、説明。
(1) ... ブラウザが iPhoneのSafariかどうか判定。
Safariであればイベントリスナを追加し、そうでなければこれ以上何もしない。
(2) ... 一本指でタッチされたらパラメータを初期化して、指の追跡開始。
(3) ... 移動中の指の位置を計測。
(4) ... 指の移動方向が↓から→へと変化するポイントを見つける。
タッチが開始されてから、横(X軸)方向に一定量(画面の横幅の1/14)動いた瞬間を検知します。その時点までに、縦(Y軸)方向に一定以上(画面の縦幅の1/4以上)動いていなければ追跡終了。これは「L字を描く」動作ではない、と判断します。
もしY軸方向に一定量移動していたならば「この瞬間が↓から→への移動方向の変化地点である」と判断して、一旦Y軸方向の値をリセットして追跡継続。
(5) ... 一連の動作に 700msec以上かかったら動作追跡を中止。
(6) ... 指が画面から離れたら…
(7) ... 指の移動方向が変化した時点から、
横(X軸)方向に一定量(画面の横幅の1/4)以上動いていて、且つ縦(Y軸)方向の動きが一定量(画面の縦幅の1/14)以内に収まっていればめでたく「L字」完成。
(8) ... フラグが立っていれば「ウインドウを閉じますか?」ダイアログを表示。そうでなければ問答無用。
ダイアログのボタンにタッチする操作でイベントが検知されるのを防ぐため、いちおうイベントリスナを無効にしてからダイアログを表示します。キャンセルされたらイベントリスナを元に戻します。
(9) ... 今、開いているウインドウが自分だけの場合に自分を閉じると、どうもその後のSafariの動作が不安定になったので、とりあえず新しい空白ウインドウを開いてから自分を閉じます。

そして、サンプルページ。iPhoneのSafariでアクセスしてみてくださいな。

  → ふつうのテキストページhttp://freefielder.jp/lab/Lflick/Lflick01.html
  → Webアプリケーションな感じのページhttp://freefielder.jp/stf/stf.php
  → PC用レイアウトの大きめなページhttp://freefielder.jp/lab/Lflick/Lflick02.html

lflick.jpgだいたい、これくらいの「L字」で反応すると思います。

で、右手首がちょっと腱鞘炎気味になるくらいフリックのテストをしながら作ってはみたものの。

これってよく考えると、Webページ側でこのスクリプトを仕込んでくれないことには Safari で使えるようにはならないのですな。

もしかしたら相当な骨折り損かもしれません。

それから、このページにはこのスクリプトを仕込んでいないのであしからず、です。

カテゴリ: