Oleksandr Gavenko's blog
2017-01-31 10:50 Swipe JS API on mobile

I implemented 2048 game in JS but it lack support for mobile devices because game input is keyboard driven.

To enable mobile devices I have to figure out how touch events is exposed by browser to JS runtime.

Information about touch events is available at:

https://www.w3.org/TR/touch-events/

Touch Events W3C Recommendation.

https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent

TouchEvent interface at MDN.

https://w3c.github.io/touch-events/

Upcoming Level 2 specification draft.

You may log corresponding events via:

var area = document.getElementById("...");

area.addEventListener("touchstart", function(ev) { console.log("%s: %o", "touchstart", ev); }, false);
area.addEventListener("touchmove", function(ev) { console.log("%s: %o", "touchmove", ev); }, false);
area.addEventListener("touchend", function(ev) { console.log("%s: %o", "touchend", ev); }, false);
area.addEventListener("touchcancel", function(ev) { console.log("%s: %o", "touchcancel", ev); }, false);

Beginning of touch is detected via touchstart and each move is logged by touchmove until you pull your finger out of screen which reported by touchend.

In order to detect simple swipe direction to left/right/up/down I hold swipe beginning position and keep holding latest updated position and create direction vector on finger release from screen:

var ANSWER = document.getElementById("answer");

var swipeStartX = null;
var swipeStartY = null;
var swipeEndX = null;
var swipeEndY = null;
function swapStart(ev) {
  swipeStartX = ev.touches[0].pageX;
  swipeStartY = ev.touches[0].pageY;
  ev.preventDefault();
}
function swapMove(ev) {
  swipeEndX = ev.touches[0].pageX;
  swipeEndY = ev.touches[0].pageY;
  ev.preventDefault();
}
function swapEnd(ev) {
  var swipeX = swipeEndX - swipeStartX;
  var swipeY = swipeEndY - swipeStartY;
  var dir = direction(swipeX, swipeY);
  if (dir) {
    ANSWER.innerHTML = dir;
  } else {
    ANSWER.innerHTML = "undetected";
  }
  swipeStartX = null;
  swipeStartY = null;
  ev.preventDefault();
}
function swapCancel(ev) { }

var area = document.getElementById("swipe-area");
area.addEventListener("touchstart", swapStart, false);
area.addEventListener("touchmove", swapMove, false);
area.addEventListener("touchend", swapEnd, false);
area.addEventListener("touchcancel", swapCancel, false);

The only missing part is direction function. I decided to ignore small moves based on some threshold. To make threshold adjusted to actual device dimension please refer to:

http://stackoverflow.com/questions/1248081/get-the-browser-viewport-dimensions-with-javascript

Get the browser viewport dimensions with JavaScript.

http://ryanve.com/lab/dimensions/

Device and Viewport Size In JavaScript.

In my simple case I use:

var sensitivity = Math.min(document.documentElement.clientWidth, document.documentElement.clientHeight);
var sensitivity = threshold*threshold / 100;
if (x*x + y*y < sensitivity)
  return null;

which mean that moves less then 1/10 of screen shortest dimension is leaved without attention.

It may be wrong for large screens but pretty OK for small screens of mobile phones. Also you may add time based restrictions. Moving on screen for more then .5 sec should mean that you are not interested in gesture...

Full implementation of direction function:

function direction(x, y) {
  var sensitivity = Math.min(document.documentElement.clientWidth, document.documentElement.clientHeight);
  var sensitivity = sensitivity*sensitivity / 100;
  if (x*x + y*y < sensitivity)
    return null;
  if (Math.abs(x) < Math.abs(y)) {
    if (y > 0)
      return "down";
    else
      return "up";
  } else {
    if (x > 0)
      return "right";
    else
      return "left";
  }
}

Full working example available at: http://hg.defun.work/exp/file/tip/web/swipe/swipe.html

My updated implementation of 2048 game available at usual place: http://2048.defun.work

See also:

http://caniuse.com/#feat=touch

Touch events browser support.

http://stackoverflow.com/questions/2264072/detect-a-finger-swipe-through-javascript-on-the-iphone-and-android

Detect a finger swipe through JavaScript on the iPhone and Android.

https://api.jquerymobile.com/swipe/

jQuery swipe API.

js, web, mobile

Feeds

all / emacs / java

Tags

adb(1), admin(1), android(1), anki(1), ansible(2), aop(1), blog(2), bytecode(1), c(1), css(2), cygwin(2), driver(1), emacs(3), fs(1), git(3), google(1), gradle(1), hardware(1), hg(2), html(1), interview(13), java(4), js(3), lang(2), lighttpd(1), markdown(1), mobile(1), naming(1), oracle(1), print(1), problem(5), python(1), quiz(6), rst(2), security(3), spring(2), sql(2), srs(1), style(1), tls(2), txt(1), unit(1), utils(1), vcs(3), web(2), win(2), windows(1)

Archive