JavascriptでHTML要素のスワイプ検知


WebサイトやUI作成時に使えるようメモ。ES2015仕様。
jQuery swipeイベントよりも、スワイプ感度の指定を簡潔に。


#1　サンプル
画面を右か左にスワイプするとページが切り替わる。
<p data-height="265" data-theme-id="0" data-slug-hash="zMdoQv" data-default-tab="js,result" data-user="snst-lab" data-pen-title="zMdoQv" class="codepen">See the Pen <a href="https://codepen.io/snst-lab/pen/zMdoQv/">zMdoQv</a> by snst.lab (<a href="https://codepen.io/snst-lab">@snst-lab</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


#2　関数の定義
```javascript

/**
* @function HTMLElement.prototype.swipe　HTML要素のスワイプを検知する
*/
 if(!HTMLElement.prototype.swipe){
  Object.defineProperty(HTMLElement.prototype, "swipe", {
    configurable: true,
    enumerable: false,
    writable: true,
    /**
    * @string direction  スワイプの方向(left, right, up, down)
    * @function callback  スワイプイベント時に実行するコールバック関数
    * @int sensitivity  スワイプの感度。値が大きいほど小さい動きで発火する。デフォルトは5 (画面サイズ/5のスワイプで発火)
    */
    value: function(direction,callback,sensitivity) {
      const self = this;
      const sens =  Object.prototype.toString.call(sensitivity)!=='[object Number]' || sensitivity <= 0 ? 5 : sensitivity;
      switch(direction){
        case 'left':
          self.addEventListener('touchstart', function (event) {
            self.removeEventListener("touchstart",null,false); //2回目以降触れただけで発火しないよう、イベントリスナを解除
            var position = event.changedTouches[0].pageX;
            self.addEventListener('touchend', function (event) {
              self.removeEventListener("touchend",null,false);
              if (event.changedTouches[0].pageX < position - screen.width / sens){
                callback(self);
              }
              position = 0;
            });
          },false);
          break;
        case 'right':
          self.addEventListener('touchstart', function (event) {
            self.removeEventListener("touchstart",null,false);  
            var position = event.changedTouches[0].pageX;
            self.addEventListener('touchend', function (event) {
              self.removeEventListener("touchend",null,false);  
              if(event.changedTouches[0].pageX > position + screen.width / sens){
                callback(self);
              }
              position = screen.width;
            });
          },false);
          break;
        case 'up':
          self.addEventListener('touchstart', function (event) {
            self.removeEventListener("touchstart",null,false);  
            var position = event.changedTouches[0].pageY;
            self.addEventListener('touchend', function (event) {
              self.removeEventListener("touchend",null,false); 
              if(event.changedTouches[0].pageY < position - screen.height / sens){
                callback(self);
              }
              position = 0;
            });
          },false);
          break;
        case 'down':
          self.addEventListener('touchstart', function (event) {
            self.removeEventListener("touchstart",null,false);  
            var position = event.changedTouches[0].pageY;
            self.addEventListener('touchend', function (event) {
              self.removeEventListener("touchend",null,false); 
              if(event.changedTouches[0].pageY > position + screen.height / sens){
                callback(self);
              }
              position = screen.height;
            });
          },false);
          break;
      }
    }
  });
}

```

#3　使用例
###HTML
```html
<div class='wall' page='1' style='background:blue;left:0;'></div >
<div class='wall' page='2' style='background:green;left:100vw;'></div >
<div class='wall' page='3' style='background:red;left:-100vw;'></div >
```

###CSS
```css
.wall{
  position:fixed;
  width:100vw; 
  height:100vh;
}
```

###Javascript
例ではjQuery使用。

```javascript
$('.wall').each(function(){
    this.swipe('left',function(dom){
        const page = Number($(dom).attr('page'));
        const next = page + 1 > 3 ? 1 : page + 1;
        const prev = page - 1 < 1 ? 3 : page - 1;
        $(dom).animate({'left':'-100vw'},500);
        $('.wall[page='+next+']').animate({'left':'0'},400);
        $('.wall[page='+prev+']').css({'left':'100vw'});
    },10);  //<-- 画面サイズ/10の動作で発火

    this.swipe('right',function(dom){
        const page = Number($(dom).attr('page'));
        const next = page - 1 < 1 ? 3 : page - 1;
        const prev = page + 1 > 3 ? 1 : page + 1;
        $(dom).animate({'left':'100vw'},500);
        $('.wall[page='+next+']').animate({'left':'0'},400);
        $('.wall[page='+prev+']').css({'left':'-100vw'});
    },10);
});
```