Данные об ориентации устройства, преобразованные в CSS, ведут себя странно при использовании реального устройства - PullRequest
1 голос
/ 18 июня 2019

Этот вопрос продолжается до предыдущего :
Я создал виджет CSS, имитирующий ориентацию телефона ( js fiddle ).При использовании вкладки датчиков dev-tools виджет работает отлично, преобразуя данные события в строку CSS rotate3d, вот так (ответ @ Andrey):

function degreesToRadians (deg) {
    return deg * Math.PI / 180;
}

class EulerAngles {
  constructor(alpha, beta, gamma) {
    this.alpha = alpha;
    this.beta = beta;
    this.gamma = gamma;
  }

  toRotate3DString() {
    const gammaAxisY = -Math.sin(degreesToRadians(this.beta));
    const gammaAxisZ = Math.cos(degreesToRadians(this.beta));
    const axis = {
      alpha: [0, 1, 0],
      beta: [-1, 0, 0],
      gamma: [0, gammaAxisY, gammaAxisZ]
    };
    return (
      "rotate3d(" +
      axis.alpha.join(",") +
      "," +
      this.alpha +
      "deg) " +
      "rotate3d(" +
      axis.beta.join(",") +
      "," +
      this.beta +
      "deg) " +
      "rotate3d(" +
      axis.gamma.join(",") +
      "," +
      this.gamma +
      "deg)"
    );
  }
}

Однако, если я использую реальное устройство (переходя на js fiddle), я получаю странное поведение, особенно когда держу телефон в портретном режиме.Это почему?как я могу это исправить?

Обновление:
После прочтения этого ответа , я думаю, моя проблема в том, что я использую углы Эйлера. Это видео объясняет это хорошо.

Однако я все еще пытаюсь преобразовать данные об ориентации устройства (альфа, бета, гамма) в стабильное преобразование CSS.

Я думал об использовании matrix3d ​​transform, но мне не хватает математических знаний для преобразования альфа, бета и гамма в матрицу 4X4.

Любая помощь будет оценена.

1 Ответ

1 голос
/ 20 июня 2019

Выяснилось, что использование Quaternion - это путь, который нужно решить, столкнувшись с этой проблемой (блокировка Гимбела). Я нашел отличную библиотеку npm для обработки математики следующим образом:

var rad = Math.PI / 180;
window.addEventListener("deviceorientation", function(ev) {

  // Update the rotation object
  var q = Quaternion.fromEuler(ev.alpha * rad, ev.beta * rad, ev.gamma * rad, 'ZXY');

  // Set the CSS style to the element you want to rotate
  elm.style.transform = "matrix3d(" + q.conjugate().toMatrix4() + ")";

}, true);
...