まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:jquery

ふと思い立って「モールモール」というパズルゲームを作ってみました。ただし「ゲーム内で使う画像はいらすとや様から入手できるものに限る」という制約を自分に課してみました。つまりいらすとや様から提供されている画像のみを、そのまま(書き足したり、一部だけ切り取ったりせずに)使ってゲームを作る、という条件にしてみました。

「モールモール」はもともと 1985 年に当時のビクター音楽産業(現JVCケンウッド・ビクターエンタテインメント)から MSX 向けにリリースされた、主人公のモグラを操作するパズルゲームでした。その後、他機種への移植や続編のリリースなどもされましたが、シンプルなルールや操作性もあってか、当時の素人プログラマー達が自分の所有していた機種に勝手に移植して雑誌で発表されていることも珍しくありませんでした。

※雑誌にプログラムコードが数ページに渡って記載されていたり、「ソノシート」と呼ばれる片面レコードにプログラム情報が記載されて付録になっていたりした時代がありました。。

実は自分もその一人 σ(^^) です。僕はパソコンの所有が大学4年生になってからと比較的遅かったのですが、高校生の頃にポケットコンピュータ(当時の通称は「ポケコン」)と呼ばれる、コンピュータというよりもプログラミング機能付き電卓を持っていました。その中の1つがシャープの PC-1350 で、当時では画期的な縦4行表示とグラフィック機能を備えており、BASIC によるプログラミングもできるものでした。この「縦複数行表示」が当時のポケコンでは珍しく、広い画面を使って「モールモール」をはじめとするゲームを勝手に移植して遊んでいたのでした。その意味で今でも思い入れあるゲームの1つです。

この「モールモール」、キャラクターとして必要な画像は6種類(ドア、はしご、土、石、イモ、主人公)と比較的少なく、また基本操作も(パズルをギブアップする時などは例外ですが)上下左右の移動のみなので矢印キーだけで実現できます。敵という概念もないので考えている間にやられてしまったり、敵を撃つ必要もありません。リソース的にも非力なポケコンにピッタリのゲームでした(笑)。

で、今回のゲーム制作にあたり、いらすとや様から以下6個の画像を使わせていただいております:

ドア =いろいろな状態のドアのイラスト



はしご =木のはしごのイラスト



 =デジタルデータ風の背景素材(緑)



 =石垣のイラスト(背景素材)



イモ =スネークフルーツのイラスト



主人公 =もぐらのイラスト



これらの画像に手を加えず、そのまま使っています。モールモールでは「土」がなぜか緑色なのですが、デジタルデータ風背景画像が遠くからみるとそれっぽく見えるのが大発見でした(苦笑)。また「イモ」の画像は数種類あったのですが、一番イモっぽく見えたのが「スネークフルーツ」だったのも新発見でした。 (^^;


で、作ってみました。github リポジトリはこちらです:
https://github.com/dotnsf/molemole


リポジトリには画像は含まれていません。必要な画像はすべて動的にいらすとや様から直接ダウンロードして使っています:
2019071801


実質 index.html ファイルだけなので GitHub Pages でも公開しました。PC ブラウザでこちらのリンク先から遊ぶことができます:
https://dotnsf.github.io/molemole/

2019071701


簡単なルールなどは README.md に記載しているので、上記ページを参照ください。簡単に言うと「すべてのイモを取ってからドアまで行けばクリア」です。ただ重力を意識する必要があることと、落ちてくる石をうまく使わないとクリアできない面があったりします。

例えば上図は第0ステージですが、この面は普通にイモを取りに行って、そのままドアまで向かえばゴールです。よほど捻くれた取り方をしない限りは詰むことはないと思います。

でも第1ステージはこうなります:
2019071703


この面の場合、何も考えずにイモを取りに行ってしまう↓と・・・、ドアにたどり着く術がなくなってしまいます。こうなると "retry" ボタンでリセットするしかありません。石をうまく誘導しながらイモを取る必要があります:
2019071704

 
先に進むともう少し複雑なステージも待っています:
2019071702


README.md にステージ追加のカスタマイズ方法も乗せているので、興味ある人はダウンロード後に自分でステージを考えて追加して遊んでみてください。



jQuery の animate 関数を使う機会があります。

この animate 関数を使うと HTML 要素に比較的簡単にアニメーション要素を加えることができます。サンプルとして 200 x 200 の矩形の左下から右上に <p> 要素を移動させる例を紹介します("animate1" ボタンをクリックすると移動します):

 




このアニメーションのために記述した CSS および JavaScript は以下になります:
<style>
div.sample{
  position: relative;
  border: 1px solid #ccc;
  width: 200px;
  height: 200px;
}
div.sample p.point{
  position: absolute;
  left: 0px;
  top: 180px;
  margin: 0;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  background-color: #d00;
}
</style>
<script>
function animateStraight(){
  var $point = $('#point1');

  var startAnimate1 = function(){
    $point.animate( { left: 180, top: 0 } );
  };

  startAnimate1();
}

</script>

<div  class="sample">
  <p  id="point1" class="point"> </p>
</div>
<button  onclick="animateStraight();">animate1</button>

</body>

初期状態で { left: 0, top: 180 } (矩形の左下)に設置されている id='#point1' の <p> 要素に対して animate() 関数を実行し、そのパラメータに { left: 180, top:0 } (矩形の右上)を指定しています。これだけで現在位置から目的位置までの間を(直線的に)移動するアニメーションが実現できます。

#細かく説明すると、#point1 の <p> 要素の left パラメータを 0 から 180 へ、top パラメータを 180 から 0 へ少しずつ移動させることで実現できています。

ここで紹介したのは位置に関するパラメータでしたが、位置以外でも数字で指定できる要素を使って現在の値から目的の値までアニメーション処理させるだけであれば同様に実現できます。


さて、本ブログエントリで紹介するのは曲線的な軌道でアニメーション移動処理させたい場合の方法です。例えば左下から右上まで、円軌道でアニメーション処理させたい場合にどうすればよいか、という場合の方法を紹介します。

この実現のために animate() 実行時のパラメータの中で step 関数を使います:
    $point.animate(
      { count: 1 },
      {
        step: function( current ){
             :
        }
      }
    );

上の例では値を変化させるパラメータに count を指定しています。値を(初期値の 0 から)1 へ変化させるという指定ですが、この count 自体は位置には関係ありません(つまりこの animate 関数自体では画面上のアニメーションの処理は行っておらず、単に count 変数を 0 から 1 へ変化させているだけです)。

アニメーション処理を行っているのは animate 関数実行時の2つ目のパラメータである step 関数です。この関数は count 関数の値が少しずつ変化するたびに、その値を引数(current)にして実行されるます。なのでこの step 関数の中で current の値を使って要素の移動位置となる x 座標および y 座標を計算して css で位置移動する、という方法によってアニメーション処理を実現します。

具体的にはこのようになります("animate2" ボタンをクリックすると移動します):

 





<style>
div.sample{
  position: relative;
  border: 1px solid #ccc;
  width: 200px;
  height: 200px;
}
div.sample p.point{
  position: absolute;
  left: 0px;
  top: 180px;
  margin: 0;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  background-color: #d00;
}
</style>
<script>
function getXY( t ){
  var r = 180;

  var x = r * t;
  var y = Math.sqrt( ( r * r ) - ( x * x ) );

  return { x: x, y: y };
}

function animateCurve(){
  var $point = $('#point2');

  var current = 0;
  var startAnimate2 = function(){
    $point.animate(
      { count: 1 },
      {
        step: function( current ){
           var point = getXY( current );
           $point.css( { left: point.x, top: point.y } );
        }
      }
    );
  };

  startAnimate2();
}
</script>

<div  class="sample">
  <p  class="point" id="point2"> </p>
</div>
<button  onclick="animateCurve();">animate2</button>

step 関数の中で current の値をパラメータに指定して getXY() 関数を実行しています。getXY() 関数では x2 + y2 = 1802 (中心座標 [0, 0] 、半径 180 の円)上において、[ 0, -180 ] から [ 180, 0 ] まで移動する間の [ x, y ] の軌跡を計算して返しています(※)。また、この getXY() 関数によって返された値を使って、<p> 要素の位置を変える、という処理を加えています。これによって animate() 関数で count の値を 0 から 1 まで直線的に移動させながら、<p> 要素の位置を円曲線に沿って移動させる、という処理を実現しています。

※この円における x 座標は 0 から 180 まで変化します。したがって、x = current * 180 で求めることができます。また x2 + y2 = 1802 より y = (1802 - x2 )の平方根なので、この数値を計算して求めています。これが getXY() 関数の中身です。

この方法を応用することで(曲線の軌道計算式がわかっていれば)animate() 関数で要素を曲線軌道でアニメーション移動させることができます。



Bootstrap を使うとモーダルダイアログを簡単に作ることができます。


モーダルダイアログは親画面の中で表示されるダイアログボックス画面のことで、「このダイアログボックスを閉じるまで親画面や他の画面に移動することができない」という特徴を持っています。利用者に質問を促して「はい」か「いいえ」のボタンを押させる、といった時の、どちらかを押すまで他の処理ができなくなる(どちらかを押す前に他の処理をされては困る)場合などに使われます。

具体的にはこんな感じで実装できます:
<html>
<head>
<meta charset="utf8"/>
<title>Bootstrap モーダルから別のモーダルへ</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</head>
<body>
  
  <nav class="navbar">
    <a href="#" class="navbar-brand">Bootstrap モーダルから別のモーダルへ</a>
  </nav>

  <!-- Button trigger modal -->
  <div class="container">
    <a href="#" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal1">モーダル1</a><br/>
    <a href="#" class="btn btn-success" data-toggle="modal" data-target="#exampleModal2">モーダル2</a>
  </div>

  <!-- Modal1 -->
  <div class="modal fade" id="exampleModal1" tabindex="-1" role="dialog" aria-labelledby="exampleModal1Label" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModal1Label">モーダル1</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">
          <p>1番目のモーダル</p>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>

  <!-- Modal2 -->
  <div class="modal fade" id="exampleModal2" tabindex="-1" role="dialog" aria-labelledby="exampleModal2Label" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModal2Label">モーダル2</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">
          <p>2番目のモーダル</p>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>
</body>
</html>

画面内には2つのモーダルダイアログ(便宜上、「モーダル1」と「モーダル2」と呼ぶことにします)が定義されていて、最初はどちらも非表示状態になっています。初期画面では2つのボタンがあり、それぞれモーダル1、モーダル2を表示するためのボタンになっています。モーダル1を表示している間、元の親画面は薄暗くグレーアウトされ、モーダル1を閉じるまではこの画面上に戻って処理を行うことはできません。モーダル2も同様です。HTML を見ていただくとわかるのですが、特別に JavaScript などを定義することもなく、Bootstrap の標準機能の一部として定義されているので、CSS の指定だけで実現できることがわかります。またモーダルダイアログ内を HTML で簡単&自由度高くカスタマイズできる点も便利です:



では「モーダル1を表示し、モーダル1を消すと同時にモーダル2を呼び出す」ということはできるでしょうか? 結論としてはできるのですが、少し JavaScript を使う必要があります。

上記を少し改良しました。モーダル1を閉じる際に「普通に閉じる」ボタンと「閉じてモーダル2を呼び出す」ボタンを用意しています。そして後者がクリックされた時に以下の JavaScript が呼び出されるように定義しました:
<html>
<head>
<meta charset="utf8"/>
<title>Bootstrap モーダルから別のモーダルへ</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script>
function changeModal(){
  $('body').removeClass( 'modal-open' );
  $('.modal-backdrop').remove();
  $('#exampleModal1').modal( 'hide' );
  
  $('#exampleModal2').modal();
}
</script>
</head>
<body>
  
  <nav class="navbar">
    <a href="#" class="navbar-brand">Bootstrap モーダルから別のモーダルへ</a>
  </nav>

  <!-- Button trigger modal -->
  <div class="container">
    <a href="#" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal1">モーダル1</a><br/>
    <a href="#" class="btn btn-success" data-toggle="modal" data-target="#exampleModal2">モーダル2</a>
  </div>

  <!-- Modal1 -->
  <div class="modal fade" id="exampleModal1" tabindex="-1" role="dialog" aria-labelledby="exampleModal1Label" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModal1Label">モーダル1</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">
          <p>1番目のモーダル</p>
          <a href="#" class="btn btn-success" onClick="changeModal()">モーダル2へ</a>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>

  <!-- Modal2 -->
  <div class="modal fade" id="exampleModal2" tabindex="-1" role="dialog" aria-labelledby="exampleModal2Label" aria-hidden="true">
    <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModal2Label">モーダル2</h5>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">×</span>
          </button>
        </div>
        <div class="modal-body">
          <p>2番目のモーダル</p>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        </div>
      </div>
    </div>
  </div>
</body>
</html>

こうすることでモーダル1を閉じて、後始末の処理も行い、その上でモーダル2を表示する、という一連の処理をすべて JavaScript で行うようにしています。これでモーダルダイアログから別のモーダルダイアログを表示することができるようになります。



HTML (特に jQueryBootstrap を併用する HTML)で表を扱う場合に便利&有名な DataTables という jQuery プラグインがあります:
2019031901


元の HTML にほんの数行追加するだけで、簡単に各列でソートできるようにしたり、ページネーションを追加したり、検索フィルタを追加することができるようになる、というスグレモノです:
2019031902


ほんの数行で簡単にできてしまう点はいいのですが、簡単に実現できるせいか、その見た目をカスタマイズしようとすると、ちとややこしめです。色々調べてみた限りでのカスタマイズ(特に検索フィルタ部分のカスタマイズ)を紹介します。


【基本 HTML】
今回カスタマイズする表は以下のような内容とします:
<table id="mytable" class="table table-bordered">
  <thead>
    <tr><th>#</th><th>name</th><th>age</th></tr>
  </thead>
  <tbody>
    <tr><td>1</td><td>鈴木</td><td>30</td></tr>
    <tr><td>2</td><td>山本</td><td>31</td></tr>
    <tr><td>3</td><td>佐藤</td><td>33</td></tr>
    <tr><td>4</td><td>木村</td><td>28</td></tr>
    <tr><td>5</td><td>井上</td><td>22</td></tr>
    <tr><td>6</td><td>船橋</td><td>20</td></tr>
    <tr><td>7</td><td>近藤</td><td>30</td></tr>
    <tr><td>8</td><td>藤原</td><td>31</td></tr>
    <tr><td>9</td><td>吉田</td><td>40</td></tr>
    <tr><td>10</td><td>鈴木</td><td>35</td></tr>
    <tr><td>11</td><td>山木</td><td>31</td></tr>
    <tr><td>12</td><td>島田</td><td>33</td></tr>
    <tr><td>13</td><td>上原</td><td>19</td></tr>
    <tr><td>14</td><td>野島</td><td>20</td></tr>
    <tr><td>15</td><td>野崎</td><td>41</td></tr>
    <tr><td>16</td><td>奥村</td><td>39</td></tr>
    <tr><td>17</td><td>佐原</td><td>32</td></tr>
    <tr><td>18</td><td>千葉</td><td>22</td></tr>
    <tr><td>19</td><td>池上</td><td>25</td></tr>
    <tr><td>20</td><td>水森</td><td>29</td></tr>
  </tbody>
</table>


Bootstrap を併用して、table & table-bordered クラスを適用しています(<table> の id は "mytable" としています)。ちなみにこのままだと見た目は以下のようになります:
#nameage
1鈴木30
2山本31
3佐藤33
4木村28
5井上22
6船橋20
7近藤30
8藤原31
9吉田40
10鈴木35
11山木31
12島田33
13上原19
14野島20
15野崎41
16奥村39
17佐原32
18千葉22
19池上25
20水森29

ではこの表を DataTables プラグインを使ってカスタマイズしていきます。


【普通に適用】
特別なカスタマイズなしに DataTables を適用します。まずは DataTables の JavaScript と CSS を CDN からロードします(この中に Bootstrap も含まれているようです):
<link rel="stylesheet" href="https://cdn.datatables.net/t/bs-3.3.6/jqc-1.12.0,dt-1.10.11/datatables.min.css"/>
<script src="https://cdn.datatables.net/t/bs-3.3.6/jqc-1.12.0,dtー1.10.11/datatables.min.js"></script>

次に表の id(="mytable")を指定して、DataTable を適用します。この時点では特にオプションは指定していません:
<script>
$(function(){
  $('#mytable').DataTable({});
});
</script>

すると上記の表は以下のようになります:
#nameage
1鈴木30
2山本31
3佐藤33
4木村28
5井上22
6船橋20
7近藤30
8藤原31
9吉田40
10鈴木35
11山木31
12島田33
13上原19
14野島20
15野崎41
16奥村39
17佐原32
18千葉22
19池上25
20水森29



特別に何を指定したわけでもないのですが、これだけで指定した表の各列の見出し部分をクリックすることでその列値によるソートが可能になります。またデフォルトで 10 件ずつのページネーションが行われ、次のページや前のページを少しずつ表示することができるようになります。更に表の右上でリアルタイム検索フィルタリングが有効になり、ここに入力した文字を含むレコードだけがフィルタリングされて表示されるようになります。ここまでが実質一行の追加でできてしまいました。

【日本語化】
上記例ではページネーションや検索フィルタリングが追加されましたが、よく見ると英語になっています。これを日本語化する方法はないでしょうか? 実はこれも簡単で、単に日本語化するだけであれば公開されているリソースファイルを使って以下の赤字部分を追加するだけです:
<script>
$(function(){
  $.extend( $.fn.dataTable.defaults, {
    language: {
      url: 'https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Japanese.json'
    }
  });
  $('#mytable').DataTable({});
});
</script>

すると上記の表は以下のようになります:
#nameage
1鈴木30
2山本31
3佐藤33
4木村28
5井上22
6船橋20
7近藤30
8藤原31
9吉田40
10鈴木35
11山木31
12島田33
13上原19
14野島20
15野崎41
16奥村39
17佐原32
18千葉22
19池上25
20水森29



指定したファイル(Japanese.json)をダウンロードして、この中身を別の日本語で書き換え、そのファイルを指定することで日本語訳を変更したり、リッチテキストにしたり、文字列ではなく画像を使ったりすることも可能です。


【ソート列の指定】
DataTables をオプション無しで適用すると表内のすべての列がソート対応になります。ここを明示的に変更することも可能です。例えば上記例で0列目(#)と2列目(age)ではソート可能にしたいが、1列目(name)ではソートできないようにしたい、という場合は以下のように(1列目のソート機能を無効に)します:
<script>
$(function(){
  $.extend( $.fn.dataTable.defaults, {
    language: {
      url: 'https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Japanese.json'
    }
  });
  $('#mytable').DataTable({
    columnDefs: [{
      targets: [ 1 ],
      orderable: false
    }]
  });
});
</script>

すると上記の表は以下のようになります:
#nameage
1鈴木30
2山本31
3佐藤33
4木村28
5井上22
6船橋20
7近藤30
8藤原31
9吉田40
10鈴木35
11山木31
12島田33
13上原19
14野島20
15野崎41
16奥村39
17佐原32
18千葉22
19池上25
20水森29



本当はもっと別の(パーツの位置変更とか)もできないわけじゃないけど、長くなりそうなので別の機会に。


 

スマホのブラウザで touchstart や touchmove、touchend イベントなどを監視することで各種タッチ処理やドラッグ、そしてスワイプといった操作を感知して処理することができます。

が、これらを使ってスワイプ(横にスライドさせるような処理)を感知しようとすると結構面倒だったりします。機種ごとの機能差についてはもちろんのこと、touchstart 時の指の場所と時間を記憶して、touchend 時の指の場所と時間を記憶し、「一定時間以内にほぼ横向きに指が移動した」ことを検知できればスワイプとみなす、といった具合に処理するわけですが、この「一定時間以内」とか、「ほぼ横向き」とか、厳密に処理するわけにもいかず、かと言ってどの程度の猶予をもたせて判断するべきか迷う要素もあったりするわけです。

そんなスワイプ処理を比較的簡単にハンドリングできるのが jQuery Mobile 内の1ファンクションである jQuery Swipe です:
2019031100


実際に jQuery Swipe を使ってスワイプ判断をするサンプルを用意しました:
<html>
<head>
<meta charset="utf8"/>
<title>swipe</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>

<script>
$(function(){
  $('#myimg').on( 'swipe', mySwipeHandler );
  function mySwipeHandler( evt ){
    alert( '#myimg swiped.' );
  }
});
</script>
</head>
<body>
<img src="https://2.bp.blogspot.com/-hvxUlVBfZUI/XG4Ga7pkzxI/AAAAAAABRrE/Q2vhHjh76T8tFTyZ7D8fFE3MCQMqiKIVgCLcBGAs/s450/champion_belt_boxing_man.png" id="myimg" width="50%"/>
</body>
</html>

HTML はシンプルに(いらすとやの)画像を1つ画面に配置しているだけです。その画像に 'swipe' イベントが発生した場合に '#myimg swiped' という警告ダイアログが表示される、というものです。jQuery と jQuery Mobile は CDN を使ってロードしています。

このコードの肝になっているのはこの部分です:
  $('#myimg').on( 'swipe', mySwipeHandler );

'#myimg' は画像に付けられた id を指定しています。つまり画像に 'swipe' イベントが発生したら mySwipeHandler 関数を実行する、という指定をしています(そして mySwipeHandler 関数では警告ダイアログが表示されます)。

この 'swipe' イベントはデフォルトだと以下の条件で発生します:
条件デフォルト値カスタマイズする場合の設定箇所
スワイプにかかる時間1000ms$.event.special.swipe.durationThreshold
横方向の移動ピクセル30ピクセル以上$.event.special.swipe.horizontalDistanceThreshold
縦方向の移動ピクセル30ピクセル以内$.event.special.swipe.verticalDistanceThreshold


つまりデフォルトではタッチ開始から終了(指を離す)まで1秒以内で、縦方向には30ピクセル以内の移動で横方向に30ピクセル以上移動するようなスワイプが発生した時に 'swipe' とみなし、そのイベントを発生させる、というものになります。変更したい場合は上述箇所を書き換えてください。


このページをアップロードし、スマホから表示するとこんな感じになります:
2019031101


イラスト部分を右や左にスワイプするとイベントが発生して、警告メッセージが表示されます:
2019031102


iPhone でも Android でも動いて楽ちん。もちろん画像以外の <div> などのパーツにも使えます。

なお、今回のサンプルでは jQuery 2.0.3 と  jQuery Mobile 1.4.5 を使っています。jQuery は 2.x であれば動くようですが、3.x だとエラーになるっぽいです(ここになかなか気づけずハマりました):
https://stackoverflow.com/questions/40172264/jquery-swipe-event-does-not-work-with-jquery-3

このページのトップヘ