0

I've created the following widget (see demo here) to mimic the sensors tab on the chrome developer tab:


enter image description here


My code listens to the orientation event of the device and tries to convert the values to fit the css transform scale, like so:

let phone = document.querySelector(".phone");
    window.addEventListener('deviceorientation', (event) => {
      phone.style.transform =
        "rotateY(" + ( event.alpha) + "deg) "
        +
        "rotateX(" + (90 - event.beta) + "deg) "
        +
        "rotateZ(" + (event.gamma ) + "deg)";
    })

However, if I play around enough with the values, my widget and the chrome widget get out of sync. Obviously, my calculations are wrong, what am I missing?

To test my code, just go to the demo open the dev tools sensors tab and play around with the widget.

Any help would be appreciated.

Update: to get to the sensors tab: Open dev tools, press Esc, on the second panel click the 3dots on the left and choose sensors.

Update: Example of problematic values are:
alpha: -77.6163
beta:-173.4458
gamma:-40.4889

Shlomi Schwartz
  • 8,693
  • 29
  • 109
  • 186
  • Luckily we can study [the source code for this dev tool](https://github.com/chromium/chromium/blob/e39d83de0ff263f20181a56482d89a1c62bb0363/third_party/blink/renderer/devtools/front_end/emulation/SensorsView.js#L370) – Andrey Jun 18 '19 at 12:50

1 Answers1

2

That is how it is done in chromium and chrome:

codepen

Essential part there is that when we apply gamma angle transformation, the axis is already rotated by previous beta angle transformation. So we need to apply gamma rotation angle not to (0, 0, 1) axis but to transformed axis which considers beta angle.

Source:

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

function ready(fn) {
  if (
    document.attachEvent
      ? document.readyState === "complete"
      : document.readyState !== "loading"
  ) {
    fn();
  } else {
    document.addEventListener("DOMContentLoaded", fn);
  }
}

ready(() => {
  let phone = document.querySelector(".phone");
  window.addEventListener("deviceorientation", event => {
    console.log(event);
    const eulerAngles = new EulerAngles(event.alpha, -90 + event.beta, event.gamma)
    phone.style.transform = eulerAngles.toRotate3DString();
  });
});
Andrey
  • 4,020
  • 21
  • 35