Orientation et accélération d'un appareil en JavaScript

Olivier Hennebelle

Cet article est un extrait du livre d'Olivier Hennebelle HTML5, CSS3 et JavaScript.
Il est publié avec l'aimable autorisation de son auteur et des éditions ENI.
Retrouvez et commandez le livre sur Amazon.

Commentez

- Titre : Orientation et accélération d'un appareil en JavaScript

- Auteur : Olivier Hennebelle

- Parution : 17 octobre 2012

- Licence : Copyright ® 2012 Olivier Hennebelle. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Gérer l'orientation du navigateur

- I-A. window.orientation

- I-B. Événement

- I-C. Aller plus loin

- II. Gérer l'accélération de l'appareil

- III. Utiliser les Media Queries en JavaScript

- IV. Remerciements

I - Gérer l'orientation du navigateur

Nous allons voir comment gérer l'orientation en JavaScript. La feuille de style s'occupant de la mise en page, le JavaScript pourra s'occuper d'autres parties dynamiques de notre page.

I-A - window.orientation

La méthode JavaScript pour définir l'orientation vient de l'objet fenêtre, il s'agit ici d'un attribut à lire et non à écrire, il s'écrit :

var test = window.orientation

Il va nous permettre de connaître l'orientation de la machine tous les 90 degrés. Il possède trois valeurs :

- 0 : orientation portrait par défaut.

- -90 : orientation de 90 degrés dans le sens des aiguilles d'une montre.

- 90 : orientation de 90 degrés dans le sens contraire des aiguilles d'une montre.

Pour tester l'orientation, nous allons créer une page HTML vide :

<!doctype html>
<html>
<head>
<meta name = "viewport" content = "user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width" />
<script type="text/javascript" src="c06RI04.js"></script>
</head>

<body onload="processor.doLoad()">
</body>
</html>

Tous le traitement se fait dans le cadre du JavaScript :

var test = window.orientation;

var montrer = 'inconnu';
if (test == 0) {
montrer = 'portrait';
} else if (test == 1) {
montrer = 'paysage à gauche';
} else if (test == -1) {
montrer = 'paysage à droite';
}

divACreer = document.createElement('div');
divACreer.innerHTML = montrer;
document.body.appendChild(divACreer);

Ce code va donc nous permettre d'afficher le type d'affichage au moment du chargement de la page. Le code en lui même est très simple, nous récupérons juste la valeur de l'orientation puis nous créons une balise div pour afficher la valeur traduite en français.

Voici donc le résultat pour une orientation portrait sur un émulateur Android :

I-B - Événement

Malheureusement, ce code a un gros défaut, il n'est appelé qu'au moment du chargement de la page. Bien sûr, nous pourrions rajouter un bouton permettant de gérer de nouveau l'orientation après son changement, mais obliger l'utilisateur à agir pour que cela soit pris en compte n'est pas acceptable.

C'est pour cela qu'il existe un événement permettant de gérer l'orientation en JavaScript : orientationchange.

Celui-ci est lancé dès que l'orientation change de 90 degrés et modifie la valeur incluse dans window.orientation.

Ainsi, il est possible de gérer le changement d'orientation au moment où il se produit.

Nous allons donc modifier notre exemple pour prendre en compte notre événement :

<!doctype html>
<html>
<head>
<meta name = "viewport" content = "user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width" />
<script type="text/javascript" src="c06RI06.js"></script>
</head>

<body>
<div id="orientationDiv">Veuillez changer l'orientation de l'écran</div>
</body>
</html>

Ainsi que le script associé :

window.onorientationchange = function() {
var test = window.orientation;

var montrer = 'inconnu';
if (test == 0) {
montrer = 'portrait';
} else if (test == 90) {
montrer = 'paysage a gauche';
} else if (test == -90) {
montrer = 'paysage a droite';
}

orientationDiv = document.getElementById('orientationDiv');
orientationDiv.innerHTML = montrer;
}

Ici nous ne faisons pas la modification au chargement (même si cela reste toujours possible) mais uniquement au moment du changement de l'orientation. Nous laissons donc le code modifier notre div pour mettre la donnée voulue.

Le résultat est le même que pour l'exemple, mais il change à chaque mouvement de l'utilisateur.

I-C - Aller plus loin

Il existe un autre attribut dans l'objet window qui est deviceOrientationEvent.

Cet attribut ne permet pas de connaître l'orientation de notre appareil de manière aussi directe mais permet d'avoir plus d'informations : l'inclinaison, la rotation et l'orientation en degrés de notre appareil.

Cet attribut est associé à un listener : deviceOrientation, qui permet de lancer une fonction JavaScript lorsque notre appareil change l'un de ces éléments.

En raison du caractère spécifique de cet attribut, il est nécessaire de tester notre page avec un appareil mobile directement. Un émulateur sur ordinateur ne pourra pas démontrer cette possibilité.

Pour comprendre comment récupérer les valeurs de l'appareil, il faut comprendre l'objet deviceOrientationEvent. Celui-ci possède trois attributs. Il s'agit en fait des trois axes de direction de notre appareil :

- alpha : indique la direction en degrés vers laquelle l'appareil est dirigé par rapport à sa boussole (partie orientation).

- beta : indique l'angle en degrés vers lequel l'appareil est penché sur un axe devant/derrière (partie inclinaison).

- gamma : indique l'angle en degrés vers lequel l'appareil est penché sur un axe gauche/droite (partie rotation).

Grâce à ce système, nous allons pouvoir connaître différentes choses spécifiques à l'utilisateur ; on peut imaginer par exemple un jeu de labyrinthe avec une bille : le seul moyen de la bouger serait justement de jouer avec cette orientation. Une chose qui n'était actuellement possible que pour les jeux en natif sur mobile est maintenant aussi disponible en HTML5.

Dans notre exemple, nous allons uniquement afficher les différentes données reçues à l'écran de manière dynamique via l'événement. Pour ce faire, nous allons écrire une page HTML ayant déjà les différentes données :

<!doctype html>
<html>
<head>
<meta name = "viewport" content = "user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width" />
<script type="text/javascript" src="c06RI08.js"></script>
</head>

<body>
<h2>Orientation de l'appareil</h2>

<table>
<tr>
<td>Orientation : </td>
<td id="alpha"></td>
</tr>
<tr>
<td>Inclinaison : </td>
<td id="beta"></td>
</tr>
<tr>
<td>Rotation : </td>
<td id="gamma"></td>
</tr>
</table>
</body>
</html>

La page en elle-même ne contient que peu de choses (un tableau pour afficher les données reçues). Voici maintenant le script qui va s'occuper de modifier les valeurs reçues par l'appareil :

window.addEventListener('deviceorientation', function(evenement) {
document.getElementById("alpha").innerHTML = Math.round( evenement.alpha );
document.getElementById("beta").innerHTML = Math.round( evenement.beta );
document.getElementById("gamma").innerHTML = Math.round( evenement.gamma );
}, false);

Math.round est utilisé ici pour avoir des chiffres entiers.

Là encore, le code est assez rapide : à chaque fois que l'on change l'orientation de notre tablette vis-à-vis des trois axes de direction, notre événement va être lancé pour mettre à jour les différentes données.

II - Gérer l'accélération de l'appareil

Les appareils mobiles ont une boussole, le HTML5 nous a fourni la possibilité de l'utiliser ; ils ont des accéléromètres, nous avons aussi la possibilité de les gérer grâce au HTML5.

Le fonctionnement de cet attribut/événement est exactement le même que le deviceorientation, excepté pour les données récupérées.

Le nom de notre attribut dans l'objet window est DeviceMotionEvent, et le nom du listener à utiliser est devicemotion.

Cet événement va nous permettre de récupérer l'accélération sur les trois axes possibles de notre appareil (tout comme le deviceorientation nous permettait de récupérer l'orientation sur les mêmes trois axes).

Ces accélérations peuvent être récupérées grâce à deux objets inclus dans notre événement :

- acceleration : données de l'accélération ne prenant pas en compte l'effet de la gravité.

- accelerationIncludingGravity : données de l'accélération avec l'effet de la gravité incluse.

Pour chaque attribut nous allons ensuite connaître l'accélération sur chaque axe : à savoir x, y et z. La différence entre les deux attributs sera donc la gravité sur l'axe sur lequel l'accélération se trouve.

Le fonctionnement étant généralement le même, nous allons directement passer à l'exemple qui, comme pour deviceorientation, ne peut être utilisé que pour un appareil équipé d'accéléromètres.

Notre page HTML va contenir nos trois axes avec, pour chacun, la valeur sans la gravité et la valeur avec :

<!doctype html>
<html>
<head>
<meta name = "viewport" content = "user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width" />
<script type="text/javascript" src="c06RI10.js"></script>
</head>

<body>
<h2>Accélération de l'appareil</h2>

<table>
<tr>
<td>Accélération sur l'axe X : </td>
<td id="axeXAvecGravite"></td>
<td> - </td>
<td id="axeXSansGravite"></td>
</tr>
<tr>
<td>Accélération sur l'axe Y : </td>
<td id="axeYAvecGravite"></td>
<td> - </td>
<td id="axeYSansGravite"></td>
</tr>
<tr>
<td>Accélération sur l'axe Z : </td>
<td id="axeZAvecGravite"></td>
<td> - </td>
<td id="axeZSansGravite"></td>
</tr>
</table>
</body>
</html>

Puis notre fichier JavaScript :

window.addEventListener('devicemotion', function(evenement) {
var acceleration = evenement.acceleration;
var accelerationSansGravite = evenement.accelerationIncludingGravity;

document.getElementById("axeXAvecGravite").innerHTML = Math.round( acceleration.x *100 ) / 100;
document.getElementById("axeXSansGravite").innerHTML = Math.round( accelerationSansGravite.x *100 ) / 100;

document.getElementById("axeYAvecGravite").innerHTML = Math.round( acceleration.y *100 ) / 100;
document.getElementById("axeYSansGravite").innerHTML = Math.round( accelerationSansGravite.y *100 ) / 100;

document.getElementById("axeZAvecGravite").innerHTML = Math.round( acceleration.z *100 ) / 100;
document.getElementById("axeZSansGravite").innerHTML = Math.round( accelerationSansGravite.z *100 ) / 100;
}, false);

III - Utiliser les Media Queries en JavaScript

Pour gérer l'orientation de notre page, il est également possible d'utiliser les media queries en JavaScript.

Cela va nous permettre de lancer différentes fonctions JavaScript en fonction de la taille de notre écran pour ajouter/supprimer des fonctionnalités à notre page.

Pour utiliser les requêtes de média, il nous faut utiliser la fonction matchMedia de notre objet window.

C'est cette fonction qui va nous permettre d'exécuter la requête de taille et ainsi la gérer dans notre JavaScript.

La fonction fonctionne comme ceci :

window.matchMedia("(min-width: 500px)")

Elle renvoie un objet de type MediaQueryList qui possède un attribut nécessaire pour connaître le résultat : matches ; il s'agit d'un booléen nous permettant de savoir si la requête donnée en paramètre est correcte ou non.

Comme tout attribut en HTML5, il est possible de gérer un listener avec celui-ci.

Son utilisation est un peu spéciale par rapport aux autres listener mais il a pourtant la même utilité : permettre de lancer une fonction au moment où l'action s'exécute.

Ici il s'agit d'un traitement un peu différent car le listener ne va pas être appelé continuellement mais uniquement au moment où la requête de média devient correcte ou non.

Ainsi, nous créons le listener de cette façon :

requeteMedia.addListener(listenerTailleEcran);

listenerTailleEcran étant une fonction de notre script.

Nous allons écrire le script qui va donc contenir une fonction utilisée pour écouter notre événement et le listener de fin de chargement de notre page. Ce listener aura pour objectif de :

- Créer notre requête de média pour une orientation de type portrait.

- Ajouter le listener pour cette requête en appelant la fonction précédemment écrite.

Notre script s'écrit comme suit :

function listenerTailleEcran(requeteMedia) {
var orientationPortrait = document.getElementById('orientationPortrait');
if (requeteMedia.matches) {
orientationPortrait.innerHTML = 'oui';
} else {
orientationPortrait.innerHTML = 'non';
}
}

document.addEventListener('DOMContentLoaded', function(){
var requeteMedia = window.matchMedia("(orientation : portrait)");
requeteMedia.addListener(listenerTailleEcran);

listenerTailleEcran(requeteMedia);
}, false);

Voici le résultat pour un affichage en mode portrait :

Et un affichage en mode paysage :

Il est possible de supprimer un listener de la même façon que l'on en ajoute un, en utilisant la fonction removeListener par exemple : requeteMedia.removeListener(listenerTailleEcran).

Le paramètre device-pixel-ratio des requêtes de média peut également être récupéré via l'attribut window.devicePixelRatio en JavaScript et donc ne nécessite pas directement de requête pour être lu.

IV - Remerciements

Cet article a été publié avec l'aimable autorisation de son auteur (Olivier Hennebelle) et des éditions ENI.

Retrouvez et commandez le livre sur Amazon.