Verwenden der Geräteausrichtung mit 3D-Transformationen

Dieser Artikel bietet Tipps zur Verwendung von Geräteausrichtungsinformationen in Kombination mit CSS 3D-Transformationen.

Verwendung der Ausrichtung zur Drehung eines Elements

Der einfachste Weg, um Ausrichtungsdaten in eine 3D-Transformation umzuwandeln, besteht im Grunde darin, die Werte alpha, gamma und beta als rotateZ, rotateX und rotateY zu verwenden.

Es ist jedoch wichtig zu beachten, dass das Koordinatensystem der Geräteausrichtung sich vom CSS-Koordinatensystem unterscheidet. Ersteres ist nämlich ein rechtshändiges System und seine Y-Achse ist positiv aufwärts, während letzteres ein linkshändiges Koordinatensystem ist, dessen Y-Achse positiv nach unten verläuft. Zudem sollten die Drehwinkel der Geräteausrichtung immer in der Reihenfolge Z - X' - Y'' erfolgen, was nicht mit der Reihenfolge einiger CSS-Transformationen übereinstimmt. Dies sind einige der praktischen Konsequenzen dieser Unterschiede:

  • Die Reihenfolge der Winkeldrehungen ist wichtig, daher stellen Sie sicher, dass die alpha-, beta- und gamma-Drehungen in dieser Reihenfolge angewendet werden.

  • Die CSS-Transformation rotate3d() und die Funktionen DOMMatrixReadOnly.rotate() und DOMMatrix.rotateSelf() wenden Winkeldrehungen in der Reihenfolge Z - Y' - X'' an, daher ist es nicht möglich, die alpha-, beta- und gamma-Drehungen in der richtigen Reihenfolge mit einem einzigen Aufruf einer dieser Funktionen anzuwenden. Stattdessen sollten Sie jede Achse einzeln in der korrekten Reihenfolge drehen.

  • Aufgrund der oben beschriebenen Unterschiede in den Koordinatensystemen werden Drehungen um den Ursprung im CSS im Uhrzeigersinn und in der Gerätenausschreibung gegen den Uhrzeigersinn vorgenommen. Dies bedeutet, dass alpha und beta invertiert werden müssen (die Drehungen um Z und X), da sie in den beiden Koordinatensystemen in unterschiedliche Richtungen weisen. Gamma (die Drehung um Y) sollte jedoch unverändert bleiben.

    Hier ist ein Codeausschnitt, um es zusammenzufassen:

    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)`;
    });
    

Konvertieren von rotate3d()-Winkeln in deviceorientation-Winkel

Falls Sie jemals einen rotate3d Achs-Winkel in Eulerschwinkel umwandeln müssen, die von deviceorientation verwendet werden, können Sie den folgenden Algorithmus verwenden:

js
// convert a rotate3d axis-angle to deviceorientation angles
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,
    // axis-angle to rotation matrix
    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);

  // rotation matrix to Euler angles
  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,
  };
}

Siehe auch