Bienvenue sur le blog de l'agence Soluka !

Retrouvez des articles dédiés aux nouveautés dans le développement web, rédigés par des passionnés, ainsi que les dernières actualités de l'agence.

Recherche

Articles populaires

Jeux Phaser

30/01/14

Hammer.js : une gestion simplifiée des événements tactiles

par Kevin le 30 janvier 2014
R&D
Image Hammer.js : une gestion simplifiée des événements tactiles

Quelle que soit l’application mobile, une bonne gestion des événements tactiles est primordiale pour permettre une bonne expérience utilisateur. Quelques plug-ins jQuery permettent de répondre à ce besoin, dont un qui fait beaucoup parler de lui en ce moment grâce à sa simplicité d’utilisation : Hammer.js.

Grâce à lui, il est possible de gérer les événements suivants :

  • le Tap et le Double Tap
  • le Drag
  • le Swipe (Drag rapide)
  • le Hold
  • le Transform (le zoom)

Pour le mettre en place, seuls 2 fichiers suffisent :

2 autres fichiers peuvent également être utiles lorsque l’on souhaite tester son code sur un ordinateur :

Une petite démonstration…

Voici une utilisation des fonctionnalités de ce plug-in avec un petit exemple :

Nous allons maintenant voir comment mettre en place cet exemple à travers le tutoriel suivant.

Le code HTML et CSS

On intègre d’abord toutes les librairies liées à jQuery et à Hammer.js.

<script type="text/javascript" src="js/lib/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="js/lib/hammer.min.js"></script>
<script type="text/javascript" src="js/lib/hammer.showtouches.js"></script>
<script type="text/javascript" src="js/lib/hammer.fakemultitouch.js"></script>
HTML - Intégration des plugins

On crée ensuite la balle avec laquelle on va interagir grâce à Hammer.js.

<body>
	<div id="container">
		<div id="ball"></div>
	</div>
</body>
HTML - Création de la balle

On met maintenant en forme la balle que l’on vient de créer.

#container {
	width: 200px;
	height: 200px;
	position: relative;
	margin: 100px auto;
}
#ball {
	width: 200px;
	height: 200px;
	position: absolute;
	border-radius: 50%;
	background: #1e5799;
}
CSS

Le code JavaScript

Pour commencer, si l’on veut tester son application sur un ordinateur, il faut avertir Hammer.js que l’on souhaite utiliser le fakeMultitouch et le showTouches.

// on affiche les zones touchées par le multitouch
if(!Hammer.HAS_TOUCHEVENTS && !Hammer.HAS_POINTEREVENTS) {
		Hammer.plugins.showTouches();
}

// on simule le multitouch grâce à SHIFT + MOUSE
if(!Hammer.HAS_TOUCHEVENTS && !Hammer.HAS_POINTEREVENTS) {
		Hammer.plugins.fakeMultitouch();
}

On déclare ensuite une variable qui va contenir un objet Hammer. Cet objet fait référence à l’élément HTML avec lequel on veut interagir. Dans notre exemple, ce sera la balle. Vous trouverez les différentes options d’instanciation d’un objet Hammer à cette adresse :
https://github.com/EightMedia/hammer.js/wiki/Getting-Started#gesture-options.

var hammer = Hammer($("#ball"), {
	transform_always_block: true,
	tap_always: false,
	drag_min_distance: 0
});
JS - Création de l'objet Hammer

Pour utiliser l’objet créé, il suffit de lui ajouter un listener qui écoutera les événements que l’on aura choisis. Dans notre cas, la balle réagira au tap, doubletap, hold, drag et transform.

hammer.on("touch tap doubletap transformstart transform dragstart drag hold", function(event) {
	ballAction(event);
});
JS - Ajout du listener sur l'objet Hammer

Une fois un événement déclenché, la fonction suivante est appelée. C’est dans cette dernière que les propriétés de la balle vont être modifiées grâce à la variable event qui contient le détail des actions de l’utilisateur.

var $ball = $("#ball");

var transform = "";
var boxShadow = "";

var scale = lastScale = 1,
	positionX = positionY = lastPositionX = lastPositionY = 0,
	pushed = false,
	square = false;

function ballAction(event) {
	switch(event.type) {

		// au touch (quel que soit l'événement), on initialise les variables
		case "touch" :
			lastScale = scale;
			lastPositionX = positionX;
			lastPositionY = positionY;
		break;

		case "tap" :
			txt = "Tap : changement de couleur";
			// couleur au hasard
			$ball.css("background", '#'+Math.floor(Math.random()*16777215).toString(16));
		break;

		case "doubletap" :
			txt = "DoubleTap : changement de forme";
			if(square)
				$ball.css("border-radius", "50%");
			else
				$ball.css("border-radius", "10px");
			square = !square;
		break;

		case "transformstart" :
			txt = "Transform : zoom sur la forme";
		break;

		case "transform" :
			scale = Math.min(2, Math.max(0.2, lastScale * event.gesture.scale));
		break;

		case "dragstart" :
			txt = "Drag : déplacement de la forme";
		break;

		case "drag" :
			positionX = lastPositionX + event.gesture.deltaX;
			positionY = lastPositionY + event.gesture.deltaY;
		break;

		case "hold" :
			txt = "Hold : on enfonce la forme";
			if(pushed)
				boxShadow = "";
			else
				boxShadow = "inset 0px 0px 53px 1px rgba(0,0,0,0.75)";
			pushed = !pushed;

			$ball.css("-webkit-box-shadow", boxShadow);
			$ball.css("-moz-box-shadow", boxShadow);
			$ball.css("box-shadow", boxShadow);
		break;
	}

	transform = "translate3d(" + positionX + "px, " + positionY + "px, 0)" +
				"scale(" + scale + ")";

	$ball.css("transform", transform);
	$ball.css("-ms-transform", transform);
	$ball.css("-webkit-transform", transform);
}
JS - Fonction appelée lorsqu'un événement est déclenché
  • fredfi

    Bonjour,

    C’est super, ça répond à ce que je cherchais. Mais …
    Sur une tablette, à cause de l’imprécision des gestes, un drag est toujours détecté à la fin d’un resize à 2 doigts. Du coup, l’objet se recentre sur l’un des doigts. Est-il possible d’avoir une solution à ce problème ?

    Merci par avance

    • Bonjour fredfi,

      J’ai trouvé une solution pour répondre à votre problème. Pour cela, il faut ajouter l’événement « transformend » sur la balle :

      hammer.on(« touch tap doubletap transformstart transform transformend dragstart drag dragend hold », function(event) {
      ballAction(event);
      });

      Ensuite, dans la fonction « balleAction(event) », il faut détecter quand l’utilisateur utilise le zoom (event « transform ») et stocker cette détection dans une variable qui ne se réinitialisera que 200 ms après que l’utilisateur ait relâché le zoom.

      var transformEnd = true;
      var funtionTimeout = null;

      function ballAction(event) {
      switch(event.type) {

      ….

      case « transformstart » :
      txt = « Transform : zoom sur la forme »;
      transformEnd = false;
      break;

      case « transformend » :
      clearTimeout(funtionTimeout);
      funtionTimeout = setTimeout(function(){transformEnd = true}, 200);
      break;

      …..

      case « dragstart » :
      if(transformEnd)
      txt = « Drag : déplacement de la forme »;
      break;

      case « drag » :
      if(transformEnd) {
      positionX = lastPositionX + event.gesture.deltaX;
      positionY = lastPositionY + event.gesture.deltaY;
      }
      break;

      …..

      }
      }

      L’objectif est en fait de ne pas déclencher l’événement « drag » lorsque que l’événement « transform » vient juste de se terminer.

      Cela répond-il à votre question ? =)

      • fredfi

        Ca marche !! Merci beaucoup. J’étais bien parti sur cette idée mais sans réussir. Y’a encore de l’espoir dans ma progression ^^

      • Pas de soucis ! N’hésitez pas si vous avez d’autres questions =)