Utiliser l'orientation de l'appareil avec les transformations 3D
================================================================

Cet article fournit des conseils sur l'utilisation des informations d'orientation d'un appareil avec les transformations 3D CSS.

Utiliser l'orientation pour tourner un élément
----------------------------------------------

La façon la plus directe de passer des données d'orientation à une transformation 3D consiste à utiliser respectivement les valeurs `alpha`, `gamma`, et `beta` pour `rotateZ`, `rotateX` et `rotateY`.

Il faut toutefois garder à l'esprit que le système de coordonnées pour les informations d'orientation de l'appareil est différent du système de coordonnées CSS. Le premier système suit la règle de la main droite et l'axe Y va croissant vers le haut, alors que le second système suit la règle de la main gauche et l'axe Y va croissant vers le bas. De plus, les rotations d'orientation de l'appareil devraient toujours être appliquées selon l'ordre Z - X' - Y''. Cet ordre ne correspond pas à certaines transformations CSS. Ces différences ont des conséquences pratiques :

* L'ordre des rotations importe : il faut s'assurer que les rotations alpha, beta et gamma sont appliquées dans cet ordre.
* La transformation CSS `rotate3d()` et les fonctions DOMMatrixReadOnly.rotate() et DOMMatrix.rotateSelf() appliquent les rotations dans l'ordre Z - Y' - X'' (et non Z - X' - Y''). Il n'est donc pas possible d'appliquer les rotations alpha, beta et gamma dans le bon ordre en utilisant un seul appel. Il faut appliquer chaque rotation individuellement, dans le bon ordre.
* Étant donné les différences de systèmes de coordonnées mentionnées avant, les rotations alpha et beta doivent être inversées (celles autour des axes Z et X), car elles pointent dans des directions opposées, et il faut garder l'angle gamma (celui autour de l'axe Y) tel quel.
 Voici un fragment de code qui résume cela :

```js
const elem = document.getElementById("view3d");

window.addEventListener("deviceorientation", (e) => {
  elem.style.transform = `rotateZ(${-e.alpha}deg) rotateX(${-e.beta}deg) rotateY(${
 e.gamma
 }deg)`;
});
```

Passer d'angles pour `rotate3d()` à ceux pour `deviceorientation`
-----------------------------------------------------------------

Si vous avez besoin de convertir des angles selon les axes utilisés par `rotate3d()` en angles d'Euler, utilisés par `deviceorientation`, vous pouvez utiliser la fonction suivante :


```js
// On convertit un angle rotate3d() en angle deviceorientation
function orient(aa) {
  const x = aa.x,
    y = aa.y,
    z = aa.z,
    a = aa.a,
    c = Math.cos(aa.a),
    s = Math.sin(aa.a),
    t = 1 - c,
    // Matrice de rotation axes-angles
    rm00 = c + x \* x \* t,
    rm10 = z \* s + y \* x \* t,
    rm20 = -y \* s + z \* x \* t,
    rm01 = -z \* s + x \* y \* t,
    rm11 = c + y \* y \* t,
    rm21 = x \* s + z \* y \* t,
    rm02 = y \* s + x \* z \* t,
    rm12 = -x \* s + y \* z \* t,
    rm22 = c + z \* z \* t,
    TO\_DEG = 180 / Math.PI,
    ea = [],
    n = Math.hypot(rm22, rm20);

  // Matrice de rotation vers les angles d'Euler
  ea[1] = Math.atan2(-rm21, n);

  if (n > 0.001) {
    ea[0] = Math.atan2(rm01, rm11);
    ea[2] = Math.atan2(rm20, rm22);
  } else {
    ea[0] = 0;
    ea[2] = (rm21 > 0 ? 1 : -1) \* Math.atan2(-rm10, rm00);
  }

  return {
    alpha: -ea[0] \* TO\_DEG - 180,
    beta: -ea[1] \* TO\_DEG,
    gamma: ea[2] \* TO\_DEG,
  };
}
```

Voir aussi
----------

* Utiliser les transformations CSS
* Détecter l'orientation de l'appareil